Merge pull request #3389 from lambdageek/bug-43099
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Thu, 11 Aug 2016 14:43:08 +0000 (10:43 -0400)
committerGitHub <noreply@github.com>
Thu, 11 Aug 2016 14:43:08 +0000 (10:43 -0400)
[coop] Temporarily restore MonoThreadInfo when TLS destructor runs.  Fixes #43099

271 files changed:
acceptance-tests/SUBMODULES.json
acceptance-tests/ms-test-suite.mk
external/nunit-lite
mcs/class/System.Data/ReferenceSources/PoolBlockingPeriod.cs [new file with mode: 0644]
mcs/class/System.Data/ReferenceSources/Res.cs
mcs/class/System.Data/mobile_System.Data.dll.sources
mcs/class/System.Data/net_4_x_System.Data.dll.sources
mcs/class/System.Runtime.Caching/ReferenceSources/SRef.cs [deleted file]
mcs/class/System.Runtime.Caching/System.Runtime.Caching.dll.sources
mcs/class/System.Runtime.Serialization/ReferenceSources/LocalAppContextSwitches.cs [new file with mode: 0644]
mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources
mcs/class/System.Web/System.Web.dll.sources
mcs/class/System.Windows.Forms/Test/System.Windows.Forms/DateTimePickerTest.cs
mcs/class/System.XML/ReferenceSources/LocalAppContextSwitches.cs
mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializationWriterTests.cs
mcs/class/System/ReferenceSources/LocalAppContextSwitches.cs [new file with mode: 0644]
mcs/class/System/ReferenceSources/SSPISafeHandles.cs
mcs/class/System/System.Net/ServicePointManager.cs
mcs/class/System/System.dll.sources
mcs/class/System/Test/System/UriTest.cs
mcs/class/System/mobile_System.dll.sources
mcs/class/corlib/ReferenceSources/AppContextSwitches.cs
mcs/class/corlib/ReferenceSources/PathInternal.cs [new file with mode: 0644]
mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs
mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs
mcs/class/corlib/System.Security.Cryptography/RSACryptoServiceProvider.cs
mcs/class/corlib/Test/System.Security.Cryptography/SignatureDescriptionTest.cs
mcs/class/corlib/Test/System/BitConverterTest.cs
mcs/class/corlib/corlib.dll.sources
mcs/class/referencesource/System.Activities.Core.Presentation/System/Activities/Core/Presentation/FlowchartConnectionPointsAdorner.cs
mcs/class/referencesource/System.Activities.Presentation/Microsoft.Tools.Common/Microsoft/Activities/Presentation/Xaml/ViewStateXamlHelper.cs
mcs/class/referencesource/System.Activities/System/Activities/Hosting/WorkflowInstance.cs
mcs/class/referencesource/System.Activities/System/Activities/WorkflowApplication.cs
mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/LocalAppContextSwitches.cs
mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/RegularExpressionAttribute.cs
mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/AppContextDefaultValues.cs
mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/LocalAppContext.cs
mcs/class/referencesource/System.Configuration/System/Configuration/ClientConfigPaths.cs
mcs/class/referencesource/System.Core/Microsoft/Win32/SafeHandles/CapiSafeHandles.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/BCryptNative.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiNative.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiSymmetricAlgorithm.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanCng.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanPublicKey.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDsaCng.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/NCryptNative.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/RsaCng.cs
mcs/class/referencesource/System.Core/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs
mcs/class/referencesource/System.Data.Entity/System/Data/Common/Utils/MetadataHelper.cs
mcs/class/referencesource/System.Data.Entity/System/Data/EntityModel/SchemaObjectModel/Schema.cs
mcs/class/referencesource/System.Data.SqlXml/System/Xml/Xsl/IlGen/XmlILOptimizerVisitor.cs
mcs/class/referencesource/System.Data/System/Data/Common/DbConnectionStringCommon.cs
mcs/class/referencesource/System.Data/System/Data/DataSet.cs
mcs/class/referencesource/System.Data/System/Data/DataTable.cs
mcs/class/referencesource/System.Data/System/Data/ProviderBase/DbConnectionPool.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlClientSymmetricKey.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlCommand.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnection.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionString.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionStringBuilder.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlInternalConnectionTds.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlParameter.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlSymmetricKeyCache.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlUtil.cs
mcs/class/referencesource/System.Data/System/Data/SqlClient/TdsEnums.cs
mcs/class/referencesource/System.Data/System/NewXml/XPathNodePointer.cs
mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/AppContextDefaultValues.cs
mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/LocalAppContext.cs
mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Claims/X509CertificateClaimSet.cs
mcs/class/referencesource/System.IdentityModel/System/IdentityModel/LocalAppContextSwitches.cs
mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs
mcs/class/referencesource/System.Runtime.Caching/System/Caching/CacheMemoryMonitor.cs
mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCache.cs
mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCacheStatistics.cs
mcs/class/referencesource/System.Runtime.Caching/System/Caching/SRef.cs
mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/DataContract.cs
mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonWriterDelegator.cs
mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaExporter.cs
mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaImporter.cs
mcs/class/referencesource/System.ServiceModel.Activation/System/ServiceModel/Activation/HostedAspNetEnvironment.cs
mcs/class/referencesource/System.ServiceModel.Internals/System/Runtime/Diagnostics/EtwDiagnosticTrace.cs
mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/AppContextDefaultValues.cs
mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/LocalAppContext.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/AppContextDefaultValues.Default.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/HttpChannelListener.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/PipeConnection.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/TransportDefaults.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/UnsafeNativeMethods.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/WebSocketHelper.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Configuration/Properties.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/MessageContractExporter.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/WsdlHelper.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/QueryMatcher.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/TaskMethodInvoker.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddress10.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddressAugust2004.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/LocalAppContextSwitches.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContext.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContextScope.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/CryptoHelper.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/TlsSspiNegotiation.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/Tokens/IssuedSecurityTokenProvider.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSSecurityPolicy.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrust.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrustServiceContract.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceHost.cs
mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceModelAppSettings.cs
mcs/class/referencesource/System.ServiceModel/System/UriTemplate.cs
mcs/class/referencesource/System.Web.DynamicData/DynamicData/DynamicValidator.cs
mcs/class/referencesource/System.Web.DynamicData/DynamicData/FieldTemplateUserControl.cs
mcs/class/referencesource/System.Web.DynamicData/DynamicData/MetaColumn.cs
mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/DataSvcMapFileLoader.cs
mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/MetadataFile.cs
mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/SvcMapFileLoader.cs
mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/ChtmlCalendarAdapter.cs
mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/WmlCalendarAdapter.cs
mcs/class/referencesource/System.Web/AspNetEventSource.cs
mcs/class/referencesource/System.Web/Cache/CacheDependency.cs
mcs/class/referencesource/System.Web/Cache/SRef.cs
mcs/class/referencesource/System.Web/Cache/cache.cs
mcs/class/referencesource/System.Web/Compilation/BuildManager.cs
mcs/class/referencesource/System.Web/Compilation/PreservationFileReader.cs
mcs/class/referencesource/System.Web/Compilation/XsdBuildProvider.cs
mcs/class/referencesource/System.Web/Configuration/BrowserCapabilitiesCodeGenerator.cs
mcs/class/referencesource/System.Web/Configuration/HttpCapabilitiesSectionHandler.cs
mcs/class/referencesource/System.Web/Configuration/RemoteWebConfigurationHostServer.cs
mcs/class/referencesource/System.Web/Handlers/TransferRequestHandler.cs
mcs/class/referencesource/System.Web/Hosting/ApplicationManager.cs
mcs/class/referencesource/System.Web/Hosting/HostingEnvironment.cs
mcs/class/referencesource/System.Web/HttpApplication.cs
mcs/class/referencesource/System.Web/HttpCacheParams.cs
mcs/class/referencesource/System.Web/HttpCachePolicy.cs
mcs/class/referencesource/System.Web/HttpCacheVary.cs
mcs/class/referencesource/System.Web/HttpCacheVaryByContentEncodings.cs
mcs/class/referencesource/System.Web/HttpContext.cs
mcs/class/referencesource/System.Web/HttpResponse.cs
mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelMetadataProvider.cs
mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidator.cs
mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidatorProvider.cs
mcs/class/referencesource/System.Web/ModelBinding/RangeAttributeAdapter.cs
mcs/class/referencesource/System.Web/ModelBinding/RegularExpressionAttributeAdapter.cs
mcs/class/referencesource/System.Web/ModelBinding/StringLengthAttributeAdapter.cs
mcs/class/referencesource/System.Web/Security/Cryptography/CryptoAlgorithms.cs
mcs/class/referencesource/System.Web/Security/FormsIdentity.cs
mcs/class/referencesource/System.Web/State/SessionStateModule.cs
mcs/class/referencesource/System.Web/State/SessionStateUtil.cs
mcs/class/referencesource/System.Web/TaskAsyncHelper.cs
mcs/class/referencesource/System.Web/UI/PartialCachingControl.cs
mcs/class/referencesource/System.Web/UI/WebControls/Calendar.cs
mcs/class/referencesource/System.Web/UI/WebControls/QueryExtensions.cs
mcs/class/referencesource/System.Web/UI/WebControls/xml.cs
mcs/class/referencesource/System.Web/Util/GCUtil.cs
mcs/class/referencesource/System.Web/Util/StringUtil.cs
mcs/class/referencesource/System.Web/Util/SynchronizationHelper.cs
mcs/class/referencesource/System.Web/Util/XmlUtils.cs
mcs/class/referencesource/System.Web/XmlSiteMapProvider.cs
mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Compiler/CompileXomlTask.cs
mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Design/ComponentSerializationService.cs
mcs/class/referencesource/System.Workflow.Runtime/Tracking.cs
mcs/class/referencesource/System.Workflow.Runtime/Tracking/TrackingProfileSerializer.cs
mcs/class/referencesource/System.Workflow.Runtime/WorkflowRuntime.cs
mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/AppContextDefaultValues.cs
mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/LocalAppContext.cs
mcs/class/referencesource/System.Xml/System/Xml/Core/AppContextDefaultValues.Defaults.cs
mcs/class/referencesource/System.Xml/System/Xml/Core/LocalAppContextSwitches.cs
mcs/class/referencesource/System.Xml/System/Xml/Serialization/Xmlcustomformatter.cs
mcs/class/referencesource/System/InternalApis/Clr/inc/AppContextDefaultValues.cs
mcs/class/referencesource/System/InternalApis/Clr/inc/LocalAppContext.cs
mcs/class/referencesource/System/InternalApis/NDP_Common/inc/PinnableBufferCache.cs
mcs/class/referencesource/System/compmod/microsoft/win32/UnsafeNativeMethods.cs
mcs/class/referencesource/System/compmod/system/componentmodel/MemberDescriptor.cs
mcs/class/referencesource/System/net/System/Net/HttpListenerRequest.cs
mcs/class/referencesource/System/net/System/Net/Internal.cs
mcs/class/referencesource/System/net/System/Net/SecureProtocols/_SslState.cs
mcs/class/referencesource/System/net/System/Net/ServicePointManager.cs
mcs/class/referencesource/System/net/System/Net/UnsafeNativeMethods.cs
mcs/class/referencesource/System/net/System/Net/_SecureChannel.cs
mcs/class/referencesource/System/net/System/_UncName.cs
mcs/class/referencesource/System/services/io/system/io/FileSystemWatcher.cs
mcs/class/referencesource/System/sys/AppContextDefaultValues.Defaults.cs
mcs/class/referencesource/System/sys/LocalAppContextSwitches.cs
mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/PartialClassGenerationTask.cs
mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/XamlBuildTaskServices.cs
mcs/class/referencesource/mscorlib/InternalApis/NDP_Common/inc/PinnableBufferCache.cs
mcs/class/referencesource/mscorlib/microsoft/win32/win32native.cs
mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs
mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs
mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.cs
mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs
mcs/class/referencesource/mscorlib/system/AppDomainSetup.cs
mcs/class/referencesource/mscorlib/system/appdomain.cs
mcs/class/referencesource/mscorlib/system/bitconverter.cs
mcs/class/referencesource/mscorlib/system/deployment/cmsutils.cs
mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/SimpleTypeInfos.cs
mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventSource.cs
mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingMetadataCollector.cs
mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs
mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs
mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs
mcs/class/referencesource/mscorlib/system/environment.cs
mcs/class/referencesource/mscorlib/system/globalization/taiwancalendar.cs
mcs/class/referencesource/mscorlib/system/io/__error.cs
mcs/class/referencesource/mscorlib/system/io/binaryreader.cs
mcs/class/referencesource/mscorlib/system/io/binarywriter.cs
mcs/class/referencesource/mscorlib/system/io/directory.cs
mcs/class/referencesource/mscorlib/system/io/directoryinfo.cs
mcs/class/referencesource/mscorlib/system/io/file.cs
mcs/class/referencesource/mscorlib/system/io/fileinfo.cs
mcs/class/referencesource/mscorlib/system/io/filestream.cs
mcs/class/referencesource/mscorlib/system/io/filesystemenumerable.cs
mcs/class/referencesource/mscorlib/system/io/filesysteminfo.cs
mcs/class/referencesource/mscorlib/system/io/longpath.cs
mcs/class/referencesource/mscorlib/system/io/path.cs
mcs/class/referencesource/mscorlib/system/resources/resourcereader.cs
mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/nativemethods.cs
mcs/class/referencesource/mscorlib/system/security/accesscontrol/filesecurity.cs
mcs/class/referencesource/mscorlib/system/security/claims/ClaimsIdentity.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/cryptoconfig.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/dsa.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/dsacryptoserviceprovider.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangedeformatter.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangeformatter.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangedeformatter.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangeformatter.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signaturedeformatter.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signatureformatter.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/signaturedescription.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/utils.cs
mcs/class/referencesource/mscorlib/system/security/cryptography/x509certificates/x509utils.cs
mcs/class/referencesource/mscorlib/system/security/permissions/fileiopermission.cs
mcs/class/referencesource/mscorlib/system/security/principal/windowsidentity.cs
mcs/class/referencesource/mscorlib/system/security/util/stringexpressionset.cs
mcs/class/referencesource/mscorlib/system/security/util/urlstring.cs
mcs/class/referencesource/mscorlib/system/text/stringbuilder.cs
mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs
mcs/mcs/assembly.cs
mcs/mcs/ikvm.cs
mcs/tests/Makefile
mcs/tests/dlls/test-939-1/test-939-lib.cs [new file with mode: 0644]
mcs/tests/dlls/test-939-1/test-939-ref.cs [new file with mode: 0644]
mcs/tests/dlls/test-939-2/test-939-lib.cs [new file with mode: 0644]
mcs/tests/dlls/test-939-common.cs [new file with mode: 0644]
mcs/tests/test-939.cs [new file with mode: 0644]
mcs/tests/test-iter-23.cs
mcs/tests/ver-il-net_4_x.xml
mcs/tools/mdoc/Makefile
mcs/tools/mkbundle/mkbundle.cs
mcs/tools/mono-api-html/AssemblyComparer.cs
mcs/tools/nunit-lite/nunit-lite-console/Console.cs
mono/metadata/cominterop.c
mono/metadata/handle.h
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/marshal.c
mono/metadata/marshal.h
mono/metadata/metadata-cross-helpers.c
mono/metadata/monitor.c
mono/metadata/monitor.h
mono/metadata/object-offsets.h
mono/mini/mini.h
mono/mini/seq-points.c
mono/mini/test_op_il_seq_point.sh
mono/tests/Makefile.am
mono/tests/priority.cs
mono/utils/mono-threads-windows.c
tools/offsets-tool/MonoAotOffsetsDumper.cs

index 7fcac6c3e9d9cbc50ff1256f936c19d96c01f72b..8287c176abcc939d505a19034ebe3baa7411df2b 100644 (file)
@@ -18,9 +18,9 @@
   {
     "name": "ms-test-suite", 
     "url": "git@github.com:xamarin/ms-test-suite.git", 
-    "rev": "840653918efed24f00f5e166094f06354cae7255", 
+    "rev": "bcd16462b0b427c582c2b4c81846a42d7ccd527f", 
     "remote-branch": "origin/master", 
     "branch": "master", 
     "directory": "ms-test-suite"
   }
-]
\ No newline at end of file
+]
index c1c16199481352d873f6df2c7a077a43197dcbe3..bd85bd494bd3b5e960de1e90ffc6c07330dbeb88 100644 (file)
@@ -1,10 +1,10 @@
 check-ms-test-suite:
        @if $(MAKE) validate-ms-test-suite RESET_VERSIONS=1; then \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -t:library -warn:1 -r:nunit.framework" && \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -debug -t:library -warn:1 -r:nunit.framework" && \
                $(MAKE) -C $(MSTESTSUITE_PATH)/conformance run NUNIT-CONSOLE="$(RUNTIME) $(CLASS)/nunit-console.exe -nologo -exclude=MonoBug,BadTest" NUNIT_XML_RESULT=$(abs_top_builddir)/acceptance-tests/TestResult-ms-test-suite-conformance.xml || EXIT_CODE=1; \
                $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup build MCS="$(MCS) -debug -warn:1" && \
                $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup run MONO="$(RUNTIME)" || EXIT_CODE=1; \
                exit $$EXIT_CODE; \
        else \
                echo "*** [ms-test-suite] Getting the repository failed, you probably don't have access to this Xamarin-internal resource. Skipping."; \
-       fi
\ No newline at end of file
+       fi
index 7065bc89e8661cad447140752c0fce118644e06e..4bc79a6da1f0ee538560b7e4d0caff46d3c86e4f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7065bc89e8661cad447140752c0fce118644e06e
+Subproject commit 4bc79a6da1f0ee538560b7e4d0caff46d3c86e4f
diff --git a/mcs/class/System.Data/ReferenceSources/PoolBlockingPeriod.cs b/mcs/class/System.Data/ReferenceSources/PoolBlockingPeriod.cs
new file mode 100644 (file)
index 0000000..82231f4
--- /dev/null
@@ -0,0 +1,9 @@
+namespace System.Data.SqlClient
+{
+       public enum PoolBlockingPeriod
+       {
+               Auto,
+               AlwaysBlock,
+               NeverBlock
+       }
+}
\ No newline at end of file
index 1fce5dcce82839c44d1805b58f449849591dc318..c103d0d1e3bf658a2717757fb01d2e7b56405504 100644 (file)
@@ -1265,6 +1265,13 @@ namespace System.Data {
                public const string SQLCR_UnrecoverableServer = "The connection is broken and recovery is not possible.  The connection is marked by the server as unrecoverable.  No attempt was made to restore the connection.";
                public const string SQLCR_UnrecoverableClient = "The connection is broken and recovery is not possible.  The connection is marked by the client driver as unrecoverable.  No attempt was made to restore the connection.";
                public const string SQLCR_NoCRAckAtReconnection = "The server did not acknowledge a recovery attempt, connection recovery is not possible.";
+
+               public const string AZURESQL_GenericEndpoint = ".database.windows.net";
+               public const string AZURESQL_GermanEndpoint = ".database.cloudapi.de";
+               public const string AZURESQL_UsGovEndpoint = ".database.usgovcloudapi.net";
+               public const string AZURESQL_ChinaEndpoint = ".database.chinacloudapi.cn";
+               public const string DbConnectionString_PoolBlockingPeriod = "Defines the blocking period behavior for a connection pool.";
+               public const string SQL_Timeout_Execution = "Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.";
        }
 
 
index a5b2a2f1492a695f255fbb5c8aaf165e5c297848..eb7e02eb03cc11bae31f3bf3836fe946b493f075 100644 (file)
@@ -6,6 +6,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/AssemblyRef.cs
 
 ReferenceSources/NativeOledbWrapper.cs
+ReferenceSources/PoolBlockingPeriod.cs
 ReferenceSources/Res.cs
 ReferenceSources/Res.missing.cs
 ReferenceSources/ResCategoryAttribute.cs
index 76b642b8849fda23403711d3dbc810bb48a6171a..c075e87489dc1b876471baf7dcc6c1853d44207f 100644 (file)
@@ -6,6 +6,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/AssemblyRef.cs
 
 ReferenceSources/NativeOledbWrapper.cs
+ReferenceSources/PoolBlockingPeriod.cs
 ReferenceSources/Res.cs
 ReferenceSources/Res.missing.cs
 ReferenceSources/ResCategoryAttribute.cs
diff --git a/mcs/class/System.Runtime.Caching/ReferenceSources/SRef.cs b/mcs/class/System.Runtime.Caching/ReferenceSources/SRef.cs
deleted file mode 100644 (file)
index 644a2fc..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace System.Runtime.Caching {
-    /*
-     * This class is used to retrieve the size of an object graph.
-     * Although Mono has not a way of computing this.
-     * Known problems:
-     *   - CacheMemoryMonitor does not trim the cache when it reaches its memory size limit.
-     *   - IMemoryCacheManager.UpdateCacheSize is called with incorrect size.
-     */
-    internal class SRef {
-
-//        private Object _sizedRef;
-
-        internal SRef (Object target) {
-//            _sizedRef = target;
-        }
-
-        internal long ApproximateSize {
-            get {
-                // TODO: .net uses System.SizedReference which contains approximate size after Gen 2 collection
-                return 16;
-            }
-        }
-
-        internal void Dispose() {
-
-        }
-    }
-}
\ No newline at end of file
index c10ee4fb4062ef8ceaa5e83a623897a2c398f9e7..46aa74c47c09cca86a99c0bb6ac0e3848fe9cda3 100644 (file)
@@ -8,7 +8,6 @@ ReferenceSources/CacheEntryCollection.cs
 ReferenceSources/CacheExpires.cs
 ReferenceSources/CacheUsage.cs
 ReferenceSources/R.Designer.cs
-ReferenceSources/SRef.cs
 ../referencesource/System.Runtime.Caching/Resources/RH.cs
 ../referencesource/System.Runtime.Caching/System/Caching/CacheEntryChangeMonitor.cs
 ../referencesource/System.Runtime.Caching/System/Caching/CacheEntryRemovedArguments.cs
@@ -51,3 +50,4 @@ ReferenceSources/SRef.cs
 ../referencesource/System.Runtime.Caching/System/Caching/SafeBitVector32.cs
 ../referencesource/System.Runtime.Caching/System/Caching/SafeRegistryHandle.cs
 ../referencesource/System.Runtime.Caching/System/Caching/SqlChangeMonitor.cs
+../referencesource/System.Runtime.Caching/System/Caching/SRef.cs
diff --git a/mcs/class/System.Runtime.Serialization/ReferenceSources/LocalAppContextSwitches.cs b/mcs/class/System.Runtime.Serialization/ReferenceSources/LocalAppContextSwitches.cs
new file mode 100644 (file)
index 0000000..ad88376
--- /dev/null
@@ -0,0 +1,7 @@
+namespace System
+{
+       static class LocalAppContextSwitches
+       {
+               public static readonly bool DoNotUseTimeZoneInfo = false;
+       }
+}
\ No newline at end of file
index 9e790d522b7eeae84c83c918ccb91584bed7e9fc..e889387651a171d9d8f467a41b0b119de29909c6 100644 (file)
@@ -4,6 +4,7 @@ Assembly/AssemblyInfo.cs
 
 ReferenceSources/DiagnosticUtility.cs
 ReferenceSources/FxTrace.cs
+ReferenceSources/LocalAppContextSwitches.cs
 ReferenceSources/SR.cs
 ReferenceSources/SR.missing.cs
 ReferenceSources/XmlExceptionHelper.cs
index 5f47d1326e0492f954a5b5b24f7965ac92264265..248b80f3537526f9501de642c6f69698a20bcf75 100644 (file)
@@ -1400,6 +1400,7 @@ ReferenceSources/SR.cs
 ../referencesource/System.Web/Hosting/IProcessHostSupportFunctions.cs
 ../referencesource/System.Web/Hosting/HTTP_COOKED_URL.cs
 ../referencesource/System.Web/Hosting/HostingEnvironmentException.cs
+../referencesource/System.Web/Util/Debug.cs
 ../referencesource/System.Web/Util/SynchronizationContextMode.cs
 ../referencesource/System.Web/Util/ISyncContextLock.cs
 ../referencesource/System.Web/Util/DoNotResetAttribute.cs
index 17156b8b708bdef62e4659b9f104360ce575f311..7fc177f9851e5e48925bc4e9c97038948f047abf 100644 (file)
@@ -3014,7 +3014,7 @@ namespace MonoTests.System.Windows.Forms {
                                 * Without this everytime a "y" or "yy" comes first in the format, it will always show as 
                                 * a 4-digit string if this is not done.
                                 */
-                               if (typeof (int).GetType ().GetType ().Name != "MonoType") {
+                               if (Type.GetType ("Mono.Runtime") == null) {
                                        // Only do this for MS, not implemented in Mono.
                                        dt.CustomFormat = "y";
                                        Assert.AreEqual ("2007", dt.Text, "#msbug1?");
index 9c961021fd64166dc4c5346af116c32dcfa138c9..bc03e96bbd8d59eb90d88e284d035889985bdf1e 100644 (file)
@@ -1,7 +1,8 @@
 namespace System
 {
-    static class LocalAppContextSwitches {
-       public const bool IgnoreEmptyKeySequences = false;
-       public const bool DontThrowOnInvalidSurrogatePairs = false;
-    }
+       static class LocalAppContextSwitches {
+               public static readonly bool IgnoreEmptyKeySequences = false;
+               public static readonly bool DontThrowOnInvalidSurrogatePairs = false;
+               public static readonly bool IgnoreKindInUtcTimeSerialization = false;
+       }
 }
\ No newline at end of file
index afa18715f265781ce3dc1238facf90df61113d8f..4b81d7366ff4d8136731bb4bf2c006ea23126b36 100644 (file)
@@ -1575,30 +1575,16 @@ namespace MonoTests.System.XmlSerialization
                        ser.Serialize (sw, d);
                        string str = sw.ToString ();
 
-                       str = RemoveTZ (str, "MyTime");
-                       str = RemoveTZ (str, "MyTimeNullable");
-
                        var expected =
 "<?xml version=\"1.0\" encoding=\"utf-16\"?>" + Environment.NewLine +
 "<root xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + Environment.NewLine +
-"  <MyTime>10:00:00.0000000$TZ$</MyTime>" + Environment.NewLine +
-"  <MyTimeNullable>10:00:00.0000000$TZ$</MyTimeNullable>" + Environment.NewLine +
+"  <MyTime>10:00:00.0000000Z</MyTime>" + Environment.NewLine +
+"  <MyTimeNullable>10:00:00.0000000Z</MyTimeNullable>" + Environment.NewLine +
 "  <MyDate>2012-01-03</MyDate>" + Environment.NewLine +
 "  <MyDateNullable>2012-01-03</MyDateNullable>" + Environment.NewLine +
 "</root>";
 
                        Assert.AreEqual (expected, str);
                }
-               
-               static string RemoveTZ (string str, string tag)
-               {
-                       var st = str.IndexOf ("<" + tag + ">");
-                       var et = str.IndexOf ("</" + tag + ">");
-                       if (st < 0 || et < 0)
-                               return str;
-
-                       var     start = str.IndexOfAny (new [] { '+', '-' }, st, et - st);
-                       return str.Substring (0, start) + "$TZ$" + str.Substring (et, str.Length - et); 
-               }
        }
 }
diff --git a/mcs/class/System/ReferenceSources/LocalAppContextSwitches.cs b/mcs/class/System/ReferenceSources/LocalAppContextSwitches.cs
new file mode 100644 (file)
index 0000000..5df7130
--- /dev/null
@@ -0,0 +1,7 @@
+namespace System
+{
+       static class LocalAppContextSwitches
+       {
+               public static readonly bool MemberDescriptorEqualsReturnsFalseIfEquivalent = false;
+       }
+}
\ No newline at end of file
index b7c1da79538d31f7ca4f93e2ccdb0a2c22cda939..a12e395cf6ff28fb4a8e97f58ec458d067cfc628 100644 (file)
@@ -133,6 +133,7 @@ namespace System.Net.Security
                        ValidateManual = 0x08,
                        NoDefaultCred = 0x10,
                        ValidateAuto = 0x20,
+                       SendAuxRecord = 0x00200000,
                        UseStrongCrypto = 0x00400000
                }
 
index 723125b1e753c867afe58eb58109b3895812ef7d..32a0148b8ea749a5796ce9d2083ca021d73f9bbf 100644 (file)
@@ -294,6 +294,10 @@ namespace System.Net
                        get { return false; }
                }
 
+               internal static bool DisableSendAuxRecord {
+                       get { return false; }
+               }
+
                // Methods
                public static void SetTcpKeepAlive (bool enabled, int keepAliveTime, int keepAliveInterval)
                {
index 4d802b3108d00c4d4ee4596a5adf7608ec0ccd29..542fa6411e00257d52b64b0955275be86b3aa4b3 100644 (file)
@@ -562,6 +562,7 @@ ReferenceSources/EnvironmentHelpers.cs
 ReferenceSources/Internal.cs
 ReferenceSources/HttpApi.cs
 ReferenceSources/HttpSysSettings.cs
+ReferenceSources/LocalAppContextSwitches.cs
 ReferenceSources/Logging.cs
 ReferenceSources/NativeMethods.cs
 ReferenceSources/RequestCacheProtocol.cs
index 9f5b848af0cb21d9e4af05662fceaa4c10b85a08..32c3fb0459e10829d7a0b9419f3eb99dfc72cd72 100644 (file)
@@ -2072,5 +2072,12 @@ namespace MonoTests.System
                        Uri uri;
                        Assert.IsTrue (Uri.TryCreate (value, UriKind.Absolute, out uri));
                }
+
+               [Test]
+               public void UncValidPath ()
+               {
+                       var uri = new Uri ("https://_foo/bar.html");
+                       Assert.AreEqual ("https", uri.Scheme);
+               }
        }
 }
index 4bba90982fe0c99561ba941382dd329f38592230..d0a70bbb58b45e7dbf72d0706ee46539597034e1 100644 (file)
@@ -305,6 +305,7 @@ ReferenceSources/CAPI.cs
 ReferenceSources/EnvironmentHelpers.cs
 ReferenceSources/HttpApi.cs
 ReferenceSources/Internal.cs
+ReferenceSources/LocalAppContextSwitches.cs
 ReferenceSources/HttpSysSettings.cs
 ReferenceSources/Logging.cs
 ReferenceSources/NativeMethods.cs
index bf8c82427e550cc93f68bf907e7f8a221596f81c..55d45d833e3f6a5c74d371e8e118d0e5861f7edd 100644 (file)
@@ -1,5 +1,6 @@
 namespace System {
        static class AppContextSwitches {
-               public const bool ThrowExceptionIfDisposedCancellationTokenSource = true;
+               public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = true;
+               public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false;
        }
 }
\ No newline at end of file
diff --git a/mcs/class/corlib/ReferenceSources/PathInternal.cs b/mcs/class/corlib/ReferenceSources/PathInternal.cs
new file mode 100644 (file)
index 0000000..828a080
--- /dev/null
@@ -0,0 +1,10 @@
+namespace System.IO
+{
+       static class PathInternal
+       {
+               public static bool IsPartiallyQualified (string path)
+               {
+                       return false;
+               }
+       }
+}
\ No newline at end of file
index a1b028b08c17a975da156186da5cb736e74ed47d..f983beeb634111f050844731b252ead7ccf04db1 100644 (file)
@@ -1051,25 +1051,21 @@ namespace System.Runtime.InteropServices
                {
                        if (s == null)
                                throw new ArgumentNullException ("s");
-                       int len = s.Length;
-                       IntPtr ctm = AllocCoTaskMem ((len+1) * 2 + 4);
-                       byte [] buffer = null;
-                       WriteInt32 (ctm, 0, len*2);
-                       try {
-                               buffer = s.GetBuffer ();
 
-                               for (int i = 0; i < len; i++)
-                                       WriteInt16 (ctm, 4 + (i * 2), (short) ((buffer [(i*2)] << 8) | (buffer [i*2+1])));
-                               WriteInt16 (ctm, 4 + buffer.Length, 0);
-                       } finally {
-                               if (buffer != null)
-                                       for (int i = buffer.Length; i > 0; ){
-                                               i--;
-                                               buffer [i] = 0;
-                                       }
+                       byte[] buffer = s.GetBuffer ();
+                       int len = s.Length;
+                       
+                       // SecureString doesn't take endian-ness into account. 
+                       // Therefore swap bytes here before we send it to c-side if little-endian.
+                       if (BitConverter.IsLittleEndian) {
+                               for (int i = 0; i < buffer.Length; i += 2) {
+                                       byte b = buffer[i];
+                                       buffer[i] = buffer[i + 1];
+                                       buffer[i + 1] = b;
+                               }
                        }
-                       return (IntPtr) ((long)ctm + 4);
-               }
+                       return BufferToBSTR (buffer, len);
+        }
 
                public static IntPtr SecureStringToCoTaskMemAnsi (SecureString s)
                {
@@ -1156,6 +1152,10 @@ namespace System.Runtime.InteropServices
                                throw ex;
                }
 
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern static IntPtr BufferToBSTR (Array ptr, int slen);
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern static IntPtr UnsafeAddrOfPinnedArrayElement (Array arr, int index);
 
index 35a574660c91850c13e2d4d65d0ed5d1c1c54f6e..369455581dac5ea9c2f0c06cf4d1582d643f6b25 100644 (file)
@@ -421,6 +421,7 @@ public partial class CryptoConfig {
                oid.Add (managedSHA1, oidSHA1);
                oid.Add (nameSHA1b, oidSHA1);
                oid.Add (nameSHA1c, oidSHA1);
+               oid.Add (nameSHA1Cng, oidSHA1);
 
                oid.Add (nameMD5, oidMD5);
                oid.Add (nameMD5a, oidMD5);
index 53667fb87dfed1dc23409f677cadaecc5236bb77..a8ebc812da3aff1068f07cb3114b0099cdc870a0 100644 (file)
@@ -36,8 +36,7 @@ using Mono.Security.Cryptography;
 
 namespace System.Security.Cryptography {
 
-       [ComVisible (true)]
-       public sealed class RSACryptoServiceProvider : RSA, ICspAsymmetricAlgorithm {
+       public partial class RSACryptoServiceProvider {
                private const int PROV_RSA_FULL = 1;    // from WinCrypt.h
                private const int AT_KEYEXCHANGE = 1;
                private const int AT_SIGNATURE = 2;
@@ -102,7 +101,7 @@ namespace System.Security.Cryptography {
 
                        // no need to load - it cannot exists
                        var p = new CspParameters (PROV_RSA_FULL);
-                       if (useMachineKeyStore)
+                       if (UseMachineKeyStore)
                                p.Flags |= CspProviderFlags.UseMachineKeyStore;
                        store = new KeyPairPersistence (p);
                }
@@ -121,13 +120,6 @@ namespace System.Security.Cryptography {
                                FromXmlString (store.KeyValue);
                        }
                }
-
-               private static bool useMachineKeyStore;
-
-               public static bool UseMachineKeyStore {
-                       get { return useMachineKeyStore; }
-                       set { useMachineKeyStore = value; }
-               }
        
                ~RSACryptoServiceProvider () 
                {
@@ -161,11 +153,7 @@ namespace System.Security.Cryptography {
                public bool PublicOnly {
                        get { return rsa.PublicOnly; }
                }
-       
-               public override string SignatureAlgorithm {
-                       get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; }
-               }
-       
+
                public byte[] Decrypt (byte[] rgb, bool fOAEP) 
                {
                        if (rgb == null)
@@ -339,6 +327,29 @@ namespace System.Security.Cryptography {
                        return PKCS1.Sign_v15 (this, hash, rgbHash);
                }
 
+               byte[] SignHash(byte[] rgbHash, int calgHash)
+               {
+                       return PKCS1.Sign_v15 (this, InternalHashToHashAlgorithm (calgHash), rgbHash);
+               }
+
+               static HashAlgorithm InternalHashToHashAlgorithm (int calgHash)
+               {
+                       switch (calgHash) {
+                       case Constants.CALG_MD5:
+                               return MD5.Create ();
+                       case Constants.CALG_SHA1:
+                               return SHA1.Create ();
+                       case Constants.CALG_SHA_256:
+                               return SHA256.Create ();
+                       case Constants.CALG_SHA_384:
+                               return SHA384.Create ();
+                       case Constants.CALG_SHA_512:
+                               return SHA512.Create ();
+                       }
+
+                       throw new NotImplementedException (calgHash.ToString ());
+               }
+
                // NOTE: this method can work with ANY configured (OID in machine.config) 
                // HashAlgorithm descendant
                public bool VerifyData (byte[] buffer, object halg, byte[] signature) 
@@ -364,6 +375,11 @@ namespace System.Security.Cryptography {
                        HashAlgorithm hash = HashAlgorithm.Create (hashName);
                        return PKCS1.Verify_v15 (this, hash, rgbHash, rgbSignature);
                }
+
+               bool VerifyHash(byte[] rgbHash, int calgHash, byte[] rgbSignature)
+               {
+                       return PKCS1.Verify_v15 (this, InternalHashToHashAlgorithm (calgHash), rgbHash, rgbSignature);
+               }
        
                protected override void Dispose (bool disposing) 
                {
@@ -444,7 +460,7 @@ namespace System.Security.Cryptography {
 
                        var p = new CspParameters (PROV_RSA_FULL);
                        p.KeyNumber = keyBlob [5] == 0x24 ? AT_SIGNATURE : AT_KEYEXCHANGE;
-                       if (useMachineKeyStore)
+                       if (UseMachineKeyStore)
                                p.Flags |= CspProviderFlags.UseMachineKeyStore;
                        store = new KeyPairPersistence (p);
                }
index 38a4aa7fafcf066f18be8fc267f3ec9e7c5dae67..c27a58f99cf7844a701f649d671d7cb79f33ae0c 100644 (file)
@@ -311,15 +311,15 @@ public class SignatureDescriptionTest {
        {
                // internal class - we cannot create one without CryptoConfig
                SignatureDescription sd = (SignatureDescription) CryptoConfig.CreateFromName ("http://www.w3.org/2000/09/xmldsig#rsa-sha1");
-               Assert.AreEqual ("System.Security.Cryptography.SHA1CryptoServiceProvider", sd.DigestAlgorithm);
+               Assert.AreEqual ("System.Security.Cryptography.SHA1Cng", sd.DigestAlgorithm);
                Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureDeformatter", sd.DeformatterAlgorithm);
                Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureFormatter", sd.FormatterAlgorithm);
-               Assert.AreEqual ("System.Security.Cryptography.RSACryptoServiceProvider", sd.KeyAlgorithm);
+               Assert.AreEqual ("System.Security.Cryptography.RSA", sd.KeyAlgorithm);
 
                HashAlgorithm hash = sd.CreateDigest();
-               Assert.AreEqual ("System.Security.Cryptography.SHA1CryptoServiceProvider", hash.ToString ());
+               Assert.AreEqual ("System.Security.Cryptography.SHA1Cng", hash.ToString ());
 
-               Assert.AreEqual (rsa.ToString (), sd.KeyAlgorithm);
+               Assert.AreEqual ("System.Security.Cryptography.RSA", sd.KeyAlgorithm);
 
                AsymmetricSignatureDeformatter asd = sd.CreateDeformatter (rsa);
                Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureDeformatter", asd.ToString ());
index 75775d3aa76e6880446463e03d4c76c30e5d496d..b69d81d5358d3b6e2b11a0c1f46fb218f063860d 100644 (file)
@@ -790,7 +790,7 @@ namespace MonoTests.System
                                Assert.IsNull (ex.InnerException, "#C3");
                                Assert.IsNotNull (ex.Message, "#C4");
                                Assert.IsNotNull (ex.ParamName, "#C5");
-                               Assert.AreEqual ("byteArray", ex.ParamName, "#C6");
+                               Assert.AreEqual ("value", ex.ParamName, "#C6");
                        }
                }
 
index 6406b39c7dac0c0aaaf3cda71452b044c5c8527f..9ef22797a960de09c6ac8e1a3998cebcebdf8dbd 100644 (file)
@@ -900,6 +900,7 @@ ReferenceSources/TextInfo.cs
 ReferenceSources/win32native.cs
 ReferenceSources/SharedStatics.cs
 ReferenceSources/SecurityContext.cs
+ReferenceSources/PathInternal.cs
 
 ../referencesource/mscorlib/system/__filters.cs
 ../referencesource/mscorlib/system/__hresults.cs
@@ -1448,6 +1449,7 @@ ReferenceSources/SecurityContext.cs
 ../referencesource/mscorlib/system/security/cryptography/ripemd160.cs
 ../referencesource/mscorlib/system/security/cryptography/ripemd160managed.cs
 ../referencesource/mscorlib/system/security/cryptography/rsa.cs
+../referencesource/mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs
 ../referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangedeformatter.cs
 ../referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangeformatter.cs
 ../referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangedeformatter.cs
index d1b3abc1dae91e1fd11ab78cb05c29b5d12daf3b..2debe1f357899ef04cc5d46f774774e6bbd3582a 100644 (file)
@@ -63,10 +63,11 @@ namespace System.Activities.Core.Presentation
                     trueLabelText = (string)virtualizingContainer.ModelItem.Properties["TrueLabel"].ComputedValue;
                 }
 
+                double pixelsPerDip = VisualTreeHelper.GetDpi(trueConnectionPoint).PixelsPerDip;
                 actualPoint = new Point(trueConnectionPoint.Location.X - origin.X, trueConnectionPoint.Location.Y - origin.Y);
                 FormattedText trueMarkerFormattedText = new FormattedText(trueLabelText, new System.Globalization.CultureInfo(textCulture),
                     this.FlowDirection, FlowchartDesigner.FlowElementCaptionTypeface, FlowchartDesigner.FlowNodeCaptionFontSize,
-                    new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor));
+                    new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor), pixelsPerDip);
                 actualPoint.Y += ConnectionPoint.DrawingLargeSide / 2;
                 actualPoint.X -= trueMarkerFormattedText.WidthIncludingTrailingWhitespace;
 
@@ -94,9 +95,10 @@ namespace System.Activities.Core.Presentation
                 actualPoint = new Point(falseConnectionPoint.Location.X - origin.X, falseConnectionPoint.Location.Y - origin.Y);
                 actualPoint.Y += ConnectionPoint.DrawingLargeSide / 2;
 
+                double pixelsPerDip = VisualTreeHelper.GetDpi(falseConnectionPoint).PixelsPerDip;
                 FormattedText falseMarkerFormattedText = new FormattedText(falseLabelText, new System.Globalization.CultureInfo(textCulture),
                     this.FlowDirection, FlowchartDesigner.FlowElementCaptionTypeface, FlowchartDesigner.FlowNodeCaptionFontSize,
-                    new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor));
+                    new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor), pixelsPerDip);
 
                 DrawtWithTransform(
                     drawingContext,
index 08bf6c294fa37029e3c1a21897810ef1cfbd9bb9..fb5266eb1310eea6c3cd141d8e608e0c68c17545 100644 (file)
@@ -7,6 +7,7 @@ namespace Microsoft.Activities.Presentation.Xaml
     using System;
     using System.Activities;
     using System.Activities.Debugger;
+    using System.Activities.DynamicUpdate;
     using System.Activities.Presentation.View;
     using System.Activities.Presentation.ViewState;
     using System.Collections.Generic;
@@ -30,6 +31,18 @@ namespace Microsoft.Activities.Presentation.Xaml
                 XamlDebuggerXmlReader.EndColumnName.MemberName
             };
 
+        // These are used to discover that we have found a DynamicUpdateInfo.OriginalDefintion or OriginalActivityBuilder
+        // attached property member. We have "hardcoded" the *MemberName" here because DynamicUpdateInfo has the
+        // AttachableMemberIdentifier properties marked as private. But the DynamicUpdateInfo class itself is public,
+        // as are the Get and Set methods.
+        static readonly string DynamicUpdateOriginalDefinitionMemberName = "OriginalDefinition";
+        static readonly MethodInfo GetOriginalDefinition = typeof(DynamicUpdateInfo).GetMethod("GetOriginalDefinition");
+        static readonly MethodInfo SetOriginalDefinition = typeof(DynamicUpdateInfo).GetMethod("SetOriginalDefinition");
+
+        static readonly string DynamicUpdateOriginalActivityBuilderMemberName = "OriginalActivityBuilder";
+        static readonly MethodInfo GetOriginalActivityBuilder = typeof(DynamicUpdateInfo).GetMethod("GetOriginalActivityBuilder");
+        static readonly MethodInfo SetOriginalActivityBuilder = typeof(DynamicUpdateInfo).GetMethod("SetOriginalActivityBuilder");
+
         // This method collects view state attached properties and generates a Xaml node stream 
         // with all view state information appearing within the ViewStateManager node. 
         // It is called when workflow definition is being serialized to string.
@@ -279,6 +292,22 @@ namespace Microsoft.Activities.Presentation.Xaml
             // Xaml member definition for IdRef. Used to identify existing IdRef properties in the input nodestream.
             XamlMember idRefMember = new XamlMember(IdRef, GetIdRef, SetIdRef, inputReader.SchemaContext);
 
+            // These are used to ignore the IdRef members that are inside a DynamicUpdateInfo.OriginalDefinition/OriginalActivityBuilder attached property.
+            // We need to ignore these because if we don't, the IdRef values for the objects in the actual workflow defintion will be ignored because of the
+            // duplicate IdRef value. This causes problems with activity designers that depend on the ViewStateManager data to correctly display the workflow
+            // on the WorkflowDesigner canvas.
+            XamlMember originalDefinitionMember = new XamlMember(DynamicUpdateOriginalDefinitionMemberName, GetOriginalDefinition, SetOriginalDefinition, inputReader.SchemaContext);
+            XamlMember originalActivityBuilderMember = new XamlMember(DynamicUpdateOriginalActivityBuilderMemberName, GetOriginalActivityBuilder, SetOriginalActivityBuilder, inputReader.SchemaContext);
+
+            // insideOriginalDefintion gets set to true when we find a "StartMember" node for either of the above two attached properties.
+            // originalDefintionMemberCount gets incremented if we find any "StartMember" and insideOriginalDefinition is true.
+            // originalDefintionMemberCount gets decremented if we find any "EndMember" and insideOriginalDefintion is true.
+            // insideOriginalDefintion gets set to false when we find an "EndMember" and originalDefinitionMemberCount gets decremented to 0.
+            // If insideOriginalDefintion is true when we find an "IdRef" member, we do NOT add that IdRef to the idRefsSeen HashSet to avoid
+            // duplicates being defined by the IdRefs inside of the OriginalDefinition attached properties.
+            bool insideOriginalDefinition = false;
+            int originalDefinitionMemberCount = 0;
+
             // Dictionary containing Ids and corresponding viewstate related
             // attached property nodes. Populated by StripViewStateElement method.
             Dictionary<string, XamlNodeList> viewStateInfo = null;
@@ -323,9 +352,21 @@ namespace Microsoft.Activities.Presentation.Xaml
                                 break;
 
                             case XamlNodeType.StartMember:
+                                // If we find a StartMember for DynamicUpdateInfo.OriginalDefinition or OriginalActivityBuilder, remember that we are
+                                // inside one of those. We don't want to "remember" IdRef values in the idRefsSeen HashSet while inside these attached properties.
+                                if (workflowDefinition.Member.Equals(originalDefinitionMember) || workflowDefinition.Member.Equals(originalActivityBuilderMember))
+                                {
+                                    insideOriginalDefinition = true;
+                                }
+                                
+                                if (insideOriginalDefinition)
+                                {
+                                    originalDefinitionMemberCount++;
+                                }
+
                                 // Track when the reader enters IdRef. Skip writing the start 
                                 // node to the output nodelist until we check for duplicates.
-                                if (workflowDefinition.Member.Equals(idRefMember))
+                                else if (workflowDefinition.Member.Equals(idRefMember))
                                 {
                                     inIdRefMember = true;
                                     skipWritingWorkflowDefinition = true;
@@ -341,38 +382,43 @@ namespace Microsoft.Activities.Presentation.Xaml
                             case XamlNodeType.Value:
                                 if (inIdRefMember)
                                 {
-                                    string idRef = workflowDefinition.Value as string;
-                                    if (!string.IsNullOrWhiteSpace(idRef))
+                                    // We don't want to deal with the IdRef if we are inside a DynamicUpdateInfo.OriginalDefinition/OriginalActivityBuilder
+                                    // attached property.
+                                    if (!insideOriginalDefinition)
                                     {
-                                        // If IdRef value is a duplicate then do not associate it with 
-                                        // the stack frame (top of stack == activity node with IdRef member on it).
-                                        if (idRefsSeen.Contains(idRef))
-                                        {
-                                            stack.Peek().IdRef = null;
-                                        }
-                                        // If the IdRef value is unique then associate it with the
-                                        // stack frame and also write its value into the output nodestream.
-                                        else
+                                        string idRef = workflowDefinition.Value as string;
+                                        if (!string.IsNullOrWhiteSpace(idRef))
                                         {
-                                            stack.Peek().IdRef = idRef;
-                                            idManager.UpdateMap(idRef);
-                                            idRefsSeen.Add(idRef);
-
-                                            if (shouldPassLineInfo)
+                                            // If IdRef value is a duplicate then do not associate it with 
+                                            // the stack frame (top of stack == activity node with IdRef member on it).
+                                            if (idRefsSeen.Contains(idRef))
                                             {
-                                                lineInfoComsumer.SetLineInfo(idRefLineNumber, idRefLinePosition);
+                                                stack.Peek().IdRef = null;
                                             }
+                                            // If the IdRef value is unique then associate it with the
+                                            // stack frame and also write its value into the output nodestream.
+                                            else
+                                            {
+                                                stack.Peek().IdRef = idRef;
+                                                idManager.UpdateMap(idRef);
+                                                idRefsSeen.Add(idRef);
 
-                                            mergedNodeWriter.WriteStartMember(idRefMember);
+                                                if (shouldPassLineInfo)
+                                                {
+                                                    lineInfoComsumer.SetLineInfo(idRefLineNumber, idRefLinePosition);
+                                                }
 
-                                            if (shouldPassLineInfo)
-                                            {
-                                                lineInfoComsumer.SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
-                                            }
+                                                mergedNodeWriter.WriteStartMember(idRefMember);
 
-                                            mergedNodeWriter.WriteValue(idRef);
+                                                if (shouldPassLineInfo)
+                                                {
+                                                    lineInfoComsumer.SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
+                                                }
 
-                                            shouldWriteIdRefEndMember = true;
+                                                mergedNodeWriter.WriteValue(idRef);
+
+                                                shouldWriteIdRefEndMember = true;
+                                            }
                                         }
                                     }
                                     // Don't need to write IdRef value into the output
@@ -382,9 +428,21 @@ namespace Microsoft.Activities.Presentation.Xaml
                                 break;
 
                             case XamlNodeType.EndMember:
+                                // If we are inside an OriginalDefinition/OriginalActivityBuilder attached property,
+                                // decrement the count and if it goes to zero, set insideOriginalDefintion to false
+                                // because we just encountered the EndMember for it.
+                                if (insideOriginalDefinition)
+                                {
+                                    originalDefinitionMemberCount--;
+                                    if (originalDefinitionMemberCount == 0)
+                                    {
+                                        insideOriginalDefinition = false;
+                                    }
+                                }
+
                                 // Exit IdRef node. Skip writing the EndMember node, we would have done 
                                 // it as part of reading the IdRef value.
-                                if (inIdRefMember)
+                                if (inIdRefMember && !insideOriginalDefinition)
                                 {
                                     inIdRefMember = false;
                                     skipWritingWorkflowDefinition = true;
@@ -401,6 +459,7 @@ namespace Microsoft.Activities.Presentation.Xaml
                                         mergedNodeWriter.WriteEndMember();
                                     }
                                 }
+
                                 break;
 
                             case XamlNodeType.EndObject:
@@ -592,6 +651,7 @@ namespace Microsoft.Activities.Presentation.Xaml
             viewStateSourceLocationMap = null;
             XamlNodeList strippedNodeList = new XamlNodeList(inputReader.SchemaContext);
             XamlMember viewStateManager = new XamlMember(ViewStateManager, GetViewStateManager, SetViewStateManager, inputReader.SchemaContext);
+
             using (XamlWriter strippedWriter = strippedNodeList.Writer)
             {
                 IXamlLineInfo lineInfo = inputReader as IXamlLineInfo;
@@ -618,7 +678,7 @@ namespace Microsoft.Activities.Presentation.Xaml
 
             return strippedNodeList.GetReader();
         }
-        
+
         // This method reads ViewStateManager nodes from the xaml nodestream and outputs that in the 
         // viewStateInfo dictionary. The input reader is positioned on the ViewStateManagerNode in the nodestream.
         static void ReadViewStateInfo(XamlReader inputReader, out Dictionary<string, XamlNodeList> viewStateInfo, out Dictionary<string, SourceLocation> viewStateSourceLocationMap)
@@ -700,7 +760,11 @@ namespace Microsoft.Activities.Presentation.Xaml
                                 }
                             }
                         } 
-                        else if (globalMemberLevel == 1 && !IsAttachablePropertyForConvert(xamlReader)) 
+                        // The xamlReader.ReadSubtree and subsequent while loop to get the Id member
+                        // has moved the xamlReader forward to the next member. We need to check to see
+                        // if it is an Attached Property that we care about. If it isn't then we need to
+                        // skip it and not put it in the resulting XamlNodeList.
+                        if (globalMemberLevel == 1 && !IsAttachablePropertyForConvert(xamlReader)) 
                         {
                             skippingUnexpectedAttachedProperty = true;
                         }
index 6b24f0ea5226a6b27bffc3bdfeb1def6cfecb873..c4cd899b81f2b89f669ac6410527694c8f28b26e 100644 (file)
@@ -48,6 +48,20 @@ namespace System.Activities.Hosting
         StackTrace abortStack;
 #endif
 
+        static WorkflowInstance()
+        {
+            try
+            {
+                using (TelemetryEventSource eventSource = new TelemetryEventSource())
+                {
+                    eventSource.V2Runtime();
+                }
+            }
+            catch
+            {
+            }
+        }
+
         protected WorkflowInstance(Activity workflowDefinition)
             : this(workflowDefinition, null)
         {
index 2090063250746eae0b7a6eaec193aac86984b785..ff9b74d7295d3a52cf91057ee647d184edec0c5e 100644 (file)
@@ -104,7 +104,7 @@ namespace System.Activities
         IList<Handle> rootExecutionProperties;
 
         IDictionary<XName, InstanceValue> instanceMetadata;
-
+        
         public WorkflowApplication(Activity workflowDefinition)
             : this(workflowDefinition, (WorkflowIdentity)null)
         {
index 20b80cfdeff85a277e06b7db9c5cb2b1f03b4c53..799f49541bb0cf99d2de4cdcca50854257bff7c7 100644 (file)
@@ -21,8 +21,10 @@ namespace System.ComponentModel.DataAnnotations {
         }
 
         public static void SetDefaultsLessOrEqual_46() {
+#pragma warning disable BCL0012 //disable warning about AppContextDefaults not following the recommended pattern
             // Define the switches that should be true for 4.6 or less, false for 4.6.1+.
             LocalAppContext.DefineSwitchDefault(UseLegacyRegExTimeoutString, true);
+#pragma warning restore BCL0012
         }
     }
 }
index cd4ac2683ec53a614da4ecbca86e00c105283167..0b0f4b3047b965e67e072297470f7516700d206a 100644 (file)
@@ -1,4 +1,4 @@
-using System.ComponentModel.DataAnnotations.Resources;
+using System.ComponentModel.DataAnnotations.Resources;
 using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Text.RegularExpressions;
@@ -19,7 +19,18 @@ namespace System.ComponentModel.DataAnnotations {
         ///     Gets or sets the timeout to use when matching the regular expression pattern (in milliseconds)
         ///     (-1 means never timeout).
         /// </summary>
-        public int MatchTimeoutInMilliseconds { get; set; } = GetDefaultTimeout();
+        public int MatchTimeoutInMilliseconds { 
+            get {
+                return _matchTimeoutInMilliseconds;
+            }
+            set {               
+                _matchTimeoutInMilliseconds = value; 
+                _matchTimeoutSet = true;
+            }
+        }
+
+        private int _matchTimeoutInMilliseconds;
+        private bool _matchTimeoutSet;
 
         private Regex Regex { get; set; }
 
@@ -90,6 +101,11 @@ namespace System.ComponentModel.DataAnnotations {
                 if (string.IsNullOrEmpty(this.Pattern)) {
                     throw new InvalidOperationException(DataAnnotationsResources.RegularExpressionAttribute_Empty_Pattern);
                 }
+
+                if (!_matchTimeoutSet) { 
+                    MatchTimeoutInMilliseconds = GetDefaultTimeout();
+                }
+
                 Regex = MatchTimeoutInMilliseconds == -1
                     ? new Regex(Pattern)
                     : Regex = new Regex(Pattern, default(RegexOptions), TimeSpan.FromMilliseconds((double)MatchTimeoutInMilliseconds));
index 8a130a0f34285449d7dc69480eff98e832bf3edd..9224bf8b8fbac5bb40399ab2c13c752e3f0fd57f 100644 (file)
@@ -3,6 +3,15 @@
 //   Copyright (c) Microsoft Corporation.  All rights reserved.
 // 
 // ==--==
+
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 using System;
 using System.Collections.Generic;
 
@@ -167,3 +176,5 @@ namespace System
         static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
     }
 }
+
+#pragma warning restore 436
index f05b599ed3d2b9af36cb7cd29c3c39123370cf6e..33662b54280621d4ef98247f98badecf87773fda 100644 (file)
@@ -4,6 +4,14 @@
 // 
 // ==--==
 
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches
 using System;
 using System.Collections.Generic;
@@ -126,3 +134,5 @@ namespace System
         }
     }
 }
+
+#pragma warning restore 436
index 4e46c61716b844e7bf2b83a0656ae5774d530d62..5ee50f1adcc536fa1881c5910f85c27e64dfbd4d 100644 (file)
@@ -26,6 +26,8 @@ namespace System.Configuration {
         const string                ClickOnceDataDirectory = "DataDirectory";
         const string                ConfigExtension = ".config";
         const int                   MAX_PATH = 260;
+        const int                   MAX_UNICODESTRING_LEN = short.MaxValue;
+        const int                   ERROR_INSUFFICIENT_BUFFER = 122; //https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
         const int                   MAX_LENGTH_TO_USE = 25;
         const string                FILE_URI_LOCAL = "file:///";
         const string                FILE_URI_UNC = "file://";
@@ -108,7 +110,18 @@ namespace System.Configuration {
                 }
                 else {
                     StringBuilder sb = new StringBuilder(MAX_PATH);
-                    UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity);
+                    int noOfTimes = 1;
+                    int length = 0;
+                    // Iterating by allocating chunk of memory each time we find the length is not sufficient.
+                    // Performance should not be an issue for current MAX_PATH length due to this change.
+                    while (((length = UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity)) == sb.Capacity) 
+                            && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER 
+                            && sb.Capacity < MAX_UNICODESTRING_LEN) {
+                        noOfTimes += 2; // increasing buffer size by 520 in each iteration - perf.
+                        int capacity = noOfTimes * MAX_PATH < MAX_UNICODESTRING_LEN ? noOfTimes * MAX_PATH : MAX_UNICODESTRING_LEN;
+                        sb.EnsureCapacity(capacity);
+                    }
+                    sb.Length = length;
                     applicationUri = Path.GetFullPath(sb.ToString());
                     applicationFilename = applicationUri;
                 }
index 16669900dca07bf55e086b30bb79912e82a4e0f0..acda796288c7143fd55a39770024a02a268db818 100644 (file)
@@ -186,6 +186,8 @@ namespace Microsoft.Win32.SafeHandles {
 #pragma warning restore 618
 #endif
     internal sealed class SafeCapiHashHandle : SafeCapiHandleBase {
+        private static volatile SafeCapiHashHandle s_invalidHandle;
+
 #if FEATURE_CORESYSTEM
         [System.Security.SecurityCritical]
 #endif
@@ -197,9 +199,17 @@ namespace Microsoft.Win32.SafeHandles {
         /// </summary>
         public static SafeCapiHashHandle InvalidHandle {
             get {
-                SafeCapiHashHandle handle = new SafeCapiHashHandle();
-                handle.SetHandle(IntPtr.Zero);
-                return handle;
+                if (s_invalidHandle == null) {
+                    // More than one of these might get created in parallel, but that's okay.
+                    // Saving one to the field saves on GC tracking, but by SuppressingFinalize on
+                    // any instance returned there's already less finalization pressure.
+                    SafeCapiHashHandle handle = new SafeCapiHashHandle();
+                    handle.SetHandle(IntPtr.Zero);
+                    GC.SuppressFinalize(handle);
+                    s_invalidHandle = handle;
+                }
+
+                return s_invalidHandle;
             }
         }
 
@@ -233,6 +243,8 @@ namespace Microsoft.Win32.SafeHandles {
 #pragma warning restore 618
 #endif
     internal sealed class SafeCapiKeyHandle : SafeCapiHandleBase {
+        private static volatile SafeCapiKeyHandle s_invalidHandle;
+
 #if FEATURE_CORESYSTEM
         [System.Security.SecurityCritical]
 #endif
@@ -245,9 +257,17 @@ namespace Microsoft.Win32.SafeHandles {
         internal static SafeCapiKeyHandle InvalidHandle {
             [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
             get {
-                SafeCapiKeyHandle handle = new SafeCapiKeyHandle();
-                handle.SetHandle(IntPtr.Zero);
-                return handle;
+                if (s_invalidHandle == null) {
+                    // More than one of these might get created in parallel, but that's okay.
+                    // Saving one to the field saves on GC tracking, but by SuppressingFinalize on
+                    // any instance returned there's already less finalization pressure.
+                    SafeCapiKeyHandle handle = new SafeCapiKeyHandle();
+                    handle.SetHandle(IntPtr.Zero);
+                    GC.SuppressFinalize(handle);
+                    s_invalidHandle = handle;
+                }
+
+                return s_invalidHandle;
             }
         }
 
index b0586886a1bde8a8283666ad4e2b02ca40036163..f4d5ebecbcf5bac9f4ef25d09a278d3b2e2c90dc 100644 (file)
@@ -38,6 +38,35 @@ namespace System.Security.Cryptography {
         /// </summary>
         Pss = 8                         // BCRYPT_PAD_PSS
     }
+#if !MONO
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct BCRYPT_DSA_KEY_BLOB_V2
+    {
+        public BCryptNative.KeyBlobMagicNumber dwMagic;  // BCRYPT_DSA_PUBLIC_MAGIC_V2 or BCRYPT_DSA_PRIVATE_MAGIC_V2
+        public int cbKey;               // key lengths in BYTES (e.g. for a 3072-bit key, cbKey = 3072/8 = 384)
+        public HASHALGORITHM_ENUM hashAlgorithm;
+        public DSAFIPSVERSION_ENUM standardVersion;
+        public int cbSeedLength;        // size (in bytes) of the seed value
+        public int cbGroupSize;         // size (in bytes) of the Q value
+        public byte Count3;             // # of iterations used to generate Q. In big-endian format.
+        public byte Count2;
+        public byte Count1;
+        public byte Count0;
+    }
+#endif
+    internal enum HASHALGORITHM_ENUM : int
+    {
+        DSA_HASH_ALGORITHM_SHA1 = 0,
+        DSA_HASH_ALGORITHM_SHA256 = 1,
+        DSA_HASH_ALGORITHM_SHA512 = 2,
+    }
+
+    internal enum DSAFIPSVERSION_ENUM : int
+    {
+        DSA_FIPS186_2 = 0,
+        DSA_FIPS186_3 = 1,
+    }
+
     /// <summary>
     ///     Native interop with CNG's BCrypt layer. Native definitions can be found in bcrypt.h
     /// </summary>
@@ -102,6 +131,10 @@ namespace System.Security.Cryptography {
         ///     Magic numbers identifying blob types
         /// </summary>
         internal enum KeyBlobMagicNumber {
+            DsaPublic = 0x42505344,                             // BCRYPT_DSA_PUBLIC_MAGIC for key lengths <= 1024 bits
+            DsaPublicV2 = 0x32425044,                           // BCRYPT_DSA_PUBLIC_MAGIC_V2 for key lengths > 1024 bits
+            DsaPrivate = 0x56505344,                            // BCRYPT_DSA_PRIVATE_MAGIC for key lengths <= 1024 bits
+            DsaPrivateV2 = 0x32565044,                          // BCRYPT_DSA_PRIVATE_MAGIC_V2 for key lengths > 1024 bits
             ECDHPublicP256 = 0x314B4345,                        // BCRYPT_ECDH_PUBLIC_P256_MAGIC
             ECDHPublicP384 = 0x334B4345,                        // BCRYPT_ECDH_PUBLIC_P384_MAGIC
             ECDHPublicP521 = 0x354B4345,                        // BCRYPT_ECDH_PUBLIC_P521_MAGIC
index b9f7080affc1c406272be2b16952e6e692c14ef8..cbf1971793da9b6ca44aaf8e92f04277de698f6d 100644 (file)
@@ -168,6 +168,14 @@ namespace System.Security.Cryptography {
             public IntPtr pbData;
         }
 
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct CERT_DSS_PARAMETERS
+        {
+            public CRYPTOAPI_BLOB p;
+            public CRYPTOAPI_BLOB q;
+            public CRYPTOAPI_BLOB g;
+        }
+
         [StructLayout(LayoutKind.Sequential)]
         internal unsafe struct PROV_ENUMALGS {
             public AlgorithmId aiAlgId;
@@ -187,6 +195,8 @@ namespace System.Security.Cryptography {
         internal const uint CALG_DSS_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY);
         internal const uint CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | ALG_SID_RSA_ANY);
         internal const uint CNG_RSA_PUBLIC_KEY_BLOB = 72;
+        internal const uint X509_DSS_PUBLICKEY = 38;
+        internal const uint X509_DSS_PARAMETERS = 39;
 
         internal const uint X509_ASN_ENCODING = 0x00000001;
         internal const uint PKCS_7_ASN_ENCODING = 0x00010000;
index 490e61651f27c5c1c6018b5306869980851c71c8..c1c5bdc3d7df9d8ca062e6e3736ccfde70a95a93 100644 (file)
@@ -447,6 +447,9 @@ namespace System.Security.Cryptography {
                                                                     buffer.Length);
                     }
                     else {
+                        if (!LocalAppContextSwitches.AesCryptoServiceProviderDontCorrectlyResetDecryptor) {
+                            resetSize = buffer.Length;
+                        }
                         CapiNative.UnsafeNativeMethods.CryptDecrypt(m_key,
                                                                     SafeCapiHashHandle.InvalidHandle,
                                                                     true,
index efb002c5814fd983a3a9fc1113cc68739d99cb7b..39a279372b4e42c6edd657af097cd31262fb7873 100644 (file)
@@ -46,6 +46,101 @@ namespace System.Security.Cryptography {
         //
 
         public abstract ECDiffieHellmanPublicKey PublicKey { get; }
-        public abstract byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey);
+
+        // This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract.
+        public virtual byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
+        {
+            throw DerivedClassMustOverride();
+        }
+
+        /// <summary>
+        /// Derive key material using the formula HASH(x) where x is the computed result of the EC Diffie-Hellman algorithm.
+        /// </summary>
+        /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
+        /// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
+        /// <returns>A hashed output suitable for key material</returns>
+        /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
+        public byte[] DeriveKeyFromHash(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm)
+        {
+            return DeriveKeyFromHash(otherPartyPublicKey, hashAlgorithm, null, null);
+        }
+
+        /// <summary>
+        /// Derive key material using the formula HASH(secretPrepend || x || secretAppend) where x is the computed
+        /// result of the EC Diffie-Hellman algorithm.
+        /// </summary>
+        /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
+        /// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
+        /// <param name="secretPrepend">A value to prepend to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
+        /// <param name="secretAppend">A value to append to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
+        /// <returns>A hashed output suitable for key material</returns>
+        /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
+        public virtual byte[] DeriveKeyFromHash(
+            ECDiffieHellmanPublicKey otherPartyPublicKey,
+            HashAlgorithmName hashAlgorithm,
+            byte[] secretPrepend,
+            byte[] secretAppend)
+        {
+            throw DerivedClassMustOverride();
+        }
+
+        /// <summary>
+        /// Derive key material using the formula HMAC(hmacKey, x) where x is the computed
+        /// result of the EC Diffie-Hellman algorithm.
+        /// </summary>
+        /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
+        /// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
+        /// <param name="hmacKey">The key to use in the HMAC. A <c>null</c> value indicates that the result of the EC Diffie-Hellman algorithm should be used as the HMAC key.</param>
+        /// <returns>A hashed output suitable for key material</returns>
+        /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
+        public byte[] DeriveKeyFromHmac(
+            ECDiffieHellmanPublicKey otherPartyPublicKey,
+            HashAlgorithmName hashAlgorithm,
+            byte[] hmacKey)
+        {
+            return DeriveKeyFromHmac(otherPartyPublicKey, hashAlgorithm, hmacKey, null, null);
+        }
+
+        /// <summary>
+        /// Derive key material using the formula HMAC(hmacKey, secretPrepend || x || secretAppend) where x is the computed
+        /// result of the EC Diffie-Hellman algorithm.
+        /// </summary>
+        /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
+        /// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
+        /// <param name="hmacKey">The key to use in the HMAC. A <c>null</c> value indicates that the result of the EC Diffie-Hellman algorithm should be used as the HMAC key.</param>
+        /// <param name="secretPrepend">A value to prepend to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
+        /// <param name="secretAppend">A value to append to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
+        /// <returns>A hashed output suitable for key material</returns>
+        /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
+        public virtual byte[] DeriveKeyFromHmac(
+            ECDiffieHellmanPublicKey otherPartyPublicKey,
+            HashAlgorithmName hashAlgorithm,
+            byte[] hmacKey,
+            byte[] secretPrepend,
+            byte[] secretAppend)
+        {
+            throw DerivedClassMustOverride();
+        }
+
+        /// <summary>
+        /// Derive key material using the TLS pseudo-random function (PRF) derivation algorithm.
+        /// </summary>
+        /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
+        /// <param name="prfLabel">The ASCII encoded PRF label.</param>
+        /// <param name="prfSeed">The 64-byte PRF seed.</param>
+        /// <returns>A 48-byte output of the TLS pseudo-random function.</returns>
+        /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="prfLabel"/> is null</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="prfSeed"/> is null</exception>
+        /// <exception cref="CryptographicException"><paramref name="prfSeed"/> is not exactly 64 bytes in length</exception>
+        public virtual byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
+        {
+            throw DerivedClassMustOverride();
+        }
+
+        private static Exception DerivedClassMustOverride()
+        {
+            return new NotImplementedException(SR.GetString(SR.NotSupported_SubclassOverride));
+        }
     }
 }
index ada0c1ac58a9ab6b51bbac975c9b48aab999237c..4a555dae5433b733b4bb56bed30a2d2a0e7f27a5 100644 (file)
@@ -93,7 +93,21 @@ namespace System.Security.Cryptography {
             }
             CodeAccessPermission.RevertAssert();
 
-            KeySize = m_key.KeySize;
+            // Our LegalKeySizes value stores the values that we encoded as being the correct
+            // legal key size limitations for this algorithm, as documented on MSDN.
+            //
+            // But on a new OS version we might not question if our limit is accurate, or MSDN
+            // could have been innacurate to start with.
+            //
+            // Since the key is already loaded, we know that Windows thought it to be valid;
+            // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
+            // check.
+            //
+            // For RSA there are known cases where this change matters. RSACryptoServiceProvider can
+            // create a 384-bit RSA key, which we consider too small to be legal. It can also create
+            // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
+            // alignment requirement. (In both cases Windows loads it just fine)
+            KeySizeValue = m_key.KeySize;
         }
 
         /// <summary>
@@ -247,7 +261,22 @@ namespace System.Security.Cryptography {
                 //
 
                 m_key = value;
-                KeySize = m_key.KeySize;
+
+                // Our LegalKeySizes value stores the values that we encoded as being the correct
+                // legal key size limitations for this algorithm, as documented on MSDN.
+                //
+                // But on a new OS version we might not question if our limit is accurate, or MSDN
+                // could have been innacurate to start with.
+                //
+                // Since the key is already loaded, we know that Windows thought it to be valid;
+                // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
+                // check.
+                //
+                // For RSA there are known cases where this change matters. RSACryptoServiceProvider can
+                // create a 384-bit RSA key, which we consider too small to be legal. It can also create
+                // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
+                // alignment requirement. (In both cases Windows loads it just fine)
+                KeySizeValue = m_key.KeySize;
             }
         }
 
@@ -369,6 +398,84 @@ namespace System.Security.Cryptography {
             }
         }
 
+        [SecuritySafeCritical]
+        public override byte[] DeriveKeyFromHash(
+            ECDiffieHellmanPublicKey otherPartyPublicKey,
+            HashAlgorithmName hashAlgorithm,
+            byte[] secretPrepend,
+            byte[] secretAppend)
+        {
+            Contract.Ensures(Contract.Result<byte[]>() != null);
+
+            if (otherPartyPublicKey == null)
+                throw new ArgumentNullException("otherPartyPublicKey");
+            if (string.IsNullOrEmpty(hashAlgorithm.Name))
+                throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm");
+
+            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
+            {
+                return NCryptNative.DeriveKeyMaterialHash(
+                    secretAgreement,
+                    hashAlgorithm.Name, 
+                    secretPrepend,
+                    secretAppend,
+                    NCryptNative.SecretAgreementFlags.None);
+            }
+        }
+
+        [SecuritySafeCritical]
+        public override byte[] DeriveKeyFromHmac(
+            ECDiffieHellmanPublicKey otherPartyPublicKey,
+            HashAlgorithmName hashAlgorithm,
+            byte[] hmacKey,
+            byte[] secretPrepend,
+            byte[] secretAppend)
+        {
+            Contract.Ensures(Contract.Result<byte[]>() != null);
+
+            if (otherPartyPublicKey == null)
+                throw new ArgumentNullException("otherPartyPublicKey");
+            if (string.IsNullOrEmpty(hashAlgorithm.Name))
+                throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm");
+
+            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
+            {
+                NCryptNative.SecretAgreementFlags flags = hmacKey == null ?
+                    NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey :
+                    NCryptNative.SecretAgreementFlags.None;
+
+                return NCryptNative.DeriveKeyMaterialHmac(
+                    secretAgreement,
+                    hashAlgorithm.Name,
+                    hmacKey,
+                    secretPrepend,
+                    secretAppend,
+                    flags);
+            }
+        }
+
+        [SecuritySafeCritical]
+        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
+        {
+            Contract.Ensures(Contract.Result<byte[]>() != null);
+
+            if (otherPartyPublicKey == null)
+                throw new ArgumentNullException("otherPartyPublicKey");
+            if (prfLabel == null)
+                throw new ArgumentNullException("prfLabel");
+            if (prfSeed == null)
+                throw new ArgumentNullException("prfSeed");
+
+            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
+            {
+                return NCryptNative.DeriveKeyMaterialTls(
+                    secretAgreement,
+                    prfLabel,
+                    prfSeed,
+                    NCryptNative.SecretAgreementFlags.None);
+            }
+        }
+
         /// <summary>
         ///     Get a handle to the secret agreement generated between two parties
         /// </summary>
index 3099a3a77e38ac7b2aaca08e34b84ecd7e651f65..91e89d8be9c4bebd3d8454aca3f17be88efe8ba1 100644 (file)
@@ -40,6 +40,10 @@ namespace System.Security.Cryptography {
             return m_keyBlob.Clone() as byte[];
         }
 
-        public abstract string ToXmlString();
+        // This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract.
+        public virtual string ToXmlString()
+        {
+            throw new NotImplementedException(SR.GetString(SR.NotSupported_SubclassOverride));
+        }
     }
 }
index c1f169ead6a2b4e72053c146499efc852c9e4f9e..1dcebb46d34ecd2ceb352a2d6b28e72cf71b33ab 100644 (file)
@@ -54,12 +54,12 @@ namespace System.Security.Cryptography {
         [SecuritySafeCritical]
         public ECDsaCng(CngKey key) {
             Contract.Ensures(LegalKeySizesValue != null);
-            Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa);
+            Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup));
 
             if (key == null) {
                 throw new ArgumentNullException("key");
             }
-            if (key.AlgorithmGroup != CngAlgorithmGroup.ECDsa) {
+            if (!IsEccAlgorithmGroup(key.AlgorithmGroup)) {
                 throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDsaRequiresECDsaKey), "key");
             }
 
@@ -83,7 +83,21 @@ namespace System.Security.Cryptography {
             }
             CodeAccessPermission.RevertAssert();
 
-            KeySize = m_key.KeySize;
+            // Our LegalKeySizes value stores the values that we encoded as being the correct
+            // legal key size limitations for this algorithm, as documented on MSDN.
+            //
+            // But on a new OS version we might not question if our limit is accurate, or MSDN
+            // could have been innacurate to start with.
+            //
+            // Since the key is already loaded, we know that Windows thought it to be valid;
+            // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
+            // check.
+            //
+            // For RSA there are known cases where this change matters. RSACryptoServiceProvider can
+            // create a 384-bit RSA key, which we consider too small to be legal. It can also create
+            // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
+            // alignment requirement. (In both cases Windows loads it just fine)
+            KeySizeValue = m_key.KeySize;
         }
 
         /// <summary>
@@ -112,8 +126,8 @@ namespace System.Security.Cryptography {
         public CngKey Key {
             get {
                 Contract.Ensures(Contract.Result<CngKey>() != null);
-                Contract.Ensures(Contract.Result<CngKey>().AlgorithmGroup == CngAlgorithmGroup.ECDsa);
-                Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa);
+                Contract.Ensures(IsEccAlgorithmGroup(Contract.Result<CngKey>().AlgorithmGroup));
+                Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup));
 
                 // If the size of the key no longer matches our stored value, then we need to replace it with
                 // a new key of the correct size.
@@ -151,9 +165,9 @@ namespace System.Security.Cryptography {
 
             private set {
                 Contract.Requires(value != null);
-                Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa);
+                Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup));
 
-                if (value.AlgorithmGroup != CngAlgorithmGroup.ECDsa) {
+                if (!IsEccAlgorithmGroup(value.AlgorithmGroup)) {
                     throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDsaRequiresECDsaKey));
                 }
 
@@ -168,7 +182,22 @@ namespace System.Security.Cryptography {
                 //
 
                 m_key = value;
-                KeySize = m_key.KeySize;
+
+                // Our LegalKeySizes value stores the values that we encoded as being the correct
+                // legal key size limitations for this algorithm, as documented on MSDN.
+                //
+                // But on a new OS version we might not question if our limit is accurate, or MSDN
+                // could have been innacurate to start with.
+                //
+                // Since the key is already loaded, we know that Windows thought it to be valid;
+                // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
+                // check.
+                //
+                // For RSA there are known cases where this change matters. RSACryptoServiceProvider can
+                // create a 384-bit RSA key, which we consider too small to be legal. It can also create
+                // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
+                // alignment requirement. (In both cases Windows loads it just fine)
+                KeySizeValue = m_key.KeySize;
             }
         }
 
@@ -416,6 +445,16 @@ namespace System.Security.Cryptography {
                 return hasher.HashFinal();
             }
         }
-    #endif
+
+        private static bool IsEccAlgorithmGroup(CngAlgorithmGroup algorithmGroup)
+        {
+            // Sometimes, when reading from certificates, ECDSA keys get identified as ECDH.
+            // Windows allows the ECDH keys to perform both key exchange (ECDH) and signing (ECDSA),
+            // so either value is acceptable for the ECDSA wrapper object.
+            //
+            // It is worth noting, however, that ECDSA-identified keys cannot be used for key exchange (ECDH) in CNG.
+            return algorithmGroup == CngAlgorithmGroup.ECDsa || algorithmGroup == CngAlgorithmGroup.ECDiffieHellman;
+        }
+#endif
     }
 }
index 8807a434240c1c3509fef6b7d2de5bf2aceb7a1b..9faf5ee01b1417400249c2658cafe30c9cec9a28 100644 (file)
@@ -796,10 +796,6 @@ namespace System.Security.Cryptography {
                                        signature,
                                        signature.Length,
                                        paddingMode);
-            if (error != ErrorCode.Success && error != ErrorCode.BadSignature) {
-                throw new CryptographicException((int)error);
-            }
-
             return error == ErrorCode.Success;
         }
 
@@ -1694,6 +1690,55 @@ namespace System.Security.Cryptography {
             return signature;
         }
 
+        /// <summary>
+        ///     Sign a hash using no padding
+        /// </summary>
+        [System.Security.SecurityCritical]
+        internal static byte[] SignHash(SafeNCryptKeyHandle key, byte[] hash, int expectedSize)
+        {
+            Contract.Requires(key != null);
+            Contract.Requires(hash != null);
+            Contract.Ensures(Contract.Result<byte[]>() != null);
+
+#if DEBUG
+            expectedSize = 1;
+#endif
+
+            // Figure out how big the signature is
+            byte[] signature = new byte[expectedSize];
+            int signatureSize = 0;
+            ErrorCode error = UnsafeNativeMethods.NCryptSignHash(key,
+                                                                 IntPtr.Zero,
+                                                                 hash,
+                                                                 hash.Length,
+                                                                 signature,
+                                                                 signature.Length,
+                                                                 out signatureSize,
+                                                                 0);
+
+            if (error == ErrorCode.BufferTooSmall)
+            {
+                signature = new byte[signatureSize];
+
+                error = UnsafeNativeMethods.NCryptSignHash(key,
+                                                           IntPtr.Zero,
+                                                           hash,
+                                                           hash.Length,
+                                                           signature,
+                                                           signature.Length,
+                                                           out signatureSize,
+                                                           0);
+            }
+
+            if (error != ErrorCode.Success)
+            {
+                throw new CryptographicException((int)error);
+            }
+
+            Array.Resize(ref signature, signatureSize);
+            return signature;
+        }
+
         /// <summary>
         ///     Unpack a key blob in ECC public blob format into its X and Y parameters
         /// 
@@ -1736,10 +1781,6 @@ namespace System.Security.Cryptography {
                                                                         signature.Length,
                                                                         0);
 
-            if (error != ErrorCode.Success && error != ErrorCode.BadSignature) {
-                throw new CryptographicException((int)error);
-            }
-
             return error == ErrorCode.Success;
         }
     }
index 842c40428e97dcde94e29ad0fcdc05a741aa0c0d..dda03fe7f378ae3ed0e1e9e785068e3941c4edc0 100644 (file)
@@ -101,7 +101,11 @@ namespace System.Security.Cryptography
                 // If we don't have a key yet, we need to generate a random one now
                 if (_key == null)
                 {
-                    CngKeyCreationParameters creationParameters = new CngKeyCreationParameters();
+                    CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
+                    {
+                        ExportPolicy = CngExportPolicies.AllowPlaintextExport,
+                    };
+
                     CngProperty keySizeProperty = new CngProperty(NCryptNative.KeyPropertyName.Length,
                                                                   BitConverter.GetBytes(KeySize),
                                                                   CngPropertyOptions.None);
@@ -126,7 +130,22 @@ namespace System.Security.Cryptography
                 }
 
                 _key = value;
-                KeySize = _key.KeySize;
+
+                // Our LegalKeySizes value stores the values that we encoded as being the correct
+                // legal key size limitations for this algorithm, as documented on MSDN.
+                //
+                // But on a new OS version we might not question if our limit is accurate, or MSDN
+                // could have been innacurate to start with.
+                //
+                // Since the key is already loaded, we know that Windows thought it to be valid;
+                // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
+                // check.
+                //
+                // For RSA there are known cases where this change matters. RSACryptoServiceProvider can
+                // create a 384-bit RSA key, which we consider too small to be legal. It can also create
+                // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
+                // alignment requirement. (In both cases Windows loads it just fine)
+                KeySizeValue = _key.KeySize;
             }
         }
 
@@ -516,6 +535,25 @@ namespace System.Security.Cryptography
                  throw new CryptographicException(SR.GetString(SR.Cryptography_UnsupportedPaddingMode));
             }
         }
+
+        /*
+         * The members
+         *   DecryptValue
+         *   EncryptValue
+         *   get_KeyExchangeAlgorithm
+         *   get_SignatureAlgorithm
+         * are all implemented on RSA as of net46.
+         *
+         * But in servicing situations, System.Core.dll can get patched onto a machine which has mscorlib < net46, meaning
+         * these abstract members have no implementation.
+         *
+         * To keep servicing simple, we'll redefine the overrides here. Since this type is sealed it only affects reflection,
+         * as there are no derived types to mis-target base.-invocations.
+         */
+        public override byte[] DecryptValue(byte[] rgb) { throw new NotSupportedException(SR.NotSupported_Method); }
+        public override byte[] EncryptValue(byte[] rgb) { throw new NotSupportedException(SR.NotSupported_Method); }
+        public override string KeyExchangeAlgorithm { get { return "RSA"; } }
+        public override string SignatureAlgorithm { get { return "RSA"; } }
 #endif
     }
 }
index e4ef01d3e6444fb6a8b667c41b4c344cf832e44a..a69b7ed8aab5202bf28520e5d0c96d5a9c614d0d 100644 (file)
@@ -71,8 +71,14 @@ namespace System.Security.Cryptography.X509Certificates
             {
                 if (privateKeyHandle == null)
                 {
+                    if (LocalAppContextSwitches.DontReliablyClonePrivateKey)
+                        return (RSA)certificate.PrivateKey;
+
                     // fall back to CAPI if we cannot acquire the key using CNG.
-                    return (RSA)certificate.PrivateKey;
+                    RSACryptoServiceProvider rsaCsp = (RSACryptoServiceProvider)certificate.PrivateKey;
+                    CspParameters cspParameters = DSACertificateExtensions.CopyCspParameters(rsaCsp);
+                    RSACryptoServiceProvider clone = new RSACryptoServiceProvider(cspParameters);
+                    return clone;
                 }
 
                 CngKey key = CngKey.Open(privateKeyHandle, CngKeyHandleOpenOptions.None);
index 1ab0fb9122e258c0ea7f8db5bd0515974b3690d3..8d7a31911c0c02eb8a7f9a9faf85b0c089a65340 100644 (file)
@@ -833,6 +833,8 @@ namespace System.Data.Common.Utils
 
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Cryptographic.Standard", "CA5350:Microsoft.Cryptographic.Standard", 
             Justification = "MD5CryptoServiceProvider is not used for cryptography/security purposes and we do it only for v1 and v1.1 for compatibility reasons.")]
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security.Cryptography", "CA5350:Microsoft.Cryptographic.Standard", 
+            Justification = "MD5CryptoServiceProvider is not used for cryptography/security purposes and we do it only for v1 and v1.1 for compatibility reasons.")]
         internal static HashAlgorithm CreateMetadataHashAlgorithm(double schemaVersion)
         {
             HashAlgorithm hashAlgorithm;
index a0388683aac19fa6d9eba4bd1693583133cebe0f..adb7b34c74d95db746287d36f2e1725400f66cbe 100644 (file)
@@ -1253,6 +1253,7 @@ namespace System.Data.EntityModel.SchemaObjectModel
                 return schemaSet;
             }
 
+            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security.Xml", "CA3060:UseXmlReaderForSchemaRead", Justification = "The schema files are embedded in the product assembly as resources")]
             private static void AddXmlSchemaToSet(XmlSchemaSet schemaSet, XmlSchemaResource schemaResource, HashSet<string> schemasAlreadyAdded)
             {
                 // loop through the children to do a depth first load
index e1c869221fa43552e2ba4aeda158583a553d307c..f671178fc0c4bde44e8228f097fdf8007979ec69 100644 (file)
@@ -2289,8 +2289,8 @@ namespace System.Xml.Xsl.IlGen {
                     if (local3.NodeType == QilNodeType.Loop) {
                         QilNode local4 = local3[0];
                         QilNode local5 = local3[1];
-                        if ( NonPositional(local2, local1) ) {
-                            // PATTERN: [CommuteFilterLoop] (Filter $iter:(For (Loop $iter2:* $ret2:*)) $cond:* ^ (NonPositional? $cond $iter)) => (Loop $iter2 (Filter $iter3:(For $ret2) (Subs $cond $iter $iter3)))
+                        if (( NonPositional(local2, local1) ) && (!( IsDocOrderDistinct(local3) ))) {
+                            // PATTERN: [CommuteFilterLoop] (Filter $iter:(For $loop:(Loop $iter2:* $ret2:*)) $cond:* ^ (NonPositional? $cond $iter) ^ ~((DocOrderDistinct? $loop))) => (Loop $iter2 (Filter $iter3:(For $ret2) (Subs $cond $iter $iter3)))
                             if (AllowReplace(XmlILOptimization.CommuteFilterLoop, local0)) {
                                 QilNode local6 = VisitFor(f.For(local5));
                                 return Replace(XmlILOptimization.CommuteFilterLoop, local0, VisitLoop(f.Loop(local4, VisitFilter(f.Filter(local6,  Subs(local2, local1, local6) )))));
index e1981b6b9dea8edd2177c16996131f8e9714e3a6..24be05dfc29dd7ee0fb6bf67d42541d9c154b058 100644 (file)
@@ -323,6 +323,143 @@ namespace System.Data.Common {
             }
         }
 
+        #region <<PoolBlockingPeriod Utility>>
+        const string PoolBlockingPeriodAutoString = "Auto";
+        const string PoolBlockingPeriodAlwaysBlockString = "AlwaysBlock";
+        const string PoolBlockingPeriodNeverBlockString = "NeverBlock";
+
+        internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result)
+        {
+            Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed");
+            Debug.Assert(null != value, "TryConvertToPoolBlockingPeriod(null,...)");
+
+            if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAutoString))
+            {
+                result = PoolBlockingPeriod.Auto;
+                return true;
+            }
+            else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAlwaysBlockString))
+            {
+                result = PoolBlockingPeriod.AlwaysBlock;
+                return true;
+            }
+            else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodNeverBlockString))
+            {
+                result = PoolBlockingPeriod.NeverBlock;
+                return true;
+            }
+            else
+            {
+                result = DbConnectionStringDefaults.PoolBlockingPeriod;
+                return false;
+            }
+        }
+
+        internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value)
+        {
+            Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed");
+            return value == PoolBlockingPeriod.Auto || value == PoolBlockingPeriod.AlwaysBlock || value == PoolBlockingPeriod.NeverBlock;
+        }
+
+        internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value)
+        {
+            Debug.Assert(IsValidPoolBlockingPeriodValue(value));
+            
+            if (value == PoolBlockingPeriod.AlwaysBlock)
+            {
+                return PoolBlockingPeriodAlwaysBlockString;
+            }
+            if (value == PoolBlockingPeriod.NeverBlock)
+            {
+                return PoolBlockingPeriodNeverBlockString;
+            }
+            else
+            {
+                return PoolBlockingPeriodAutoString;
+            }
+        }
+
+        /// <summary>
+        /// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is:
+        /// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer
+        /// * if the value is from type PoolBlockingPeriod, it will be used as is
+        /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum
+        /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException
+        /// 
+        /// in any case above, if the conerted value is out of valid range, the method raises ArgumentOutOfRangeException.
+        /// </summary>
+        /// <returns>PoolBlockingPeriod value in the valid range</returns>
+        internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value)
+        {
+            Debug.Assert(null != value, "ConvertToPoolBlockingPeriod(null)");
+            string sValue = (value as string);
+            PoolBlockingPeriod result;
+            if (null != sValue)
+            {
+                // We could use Enum.TryParse<PoolBlockingPeriod> here, but it accepts value combinations like
+                // "ReadOnly, ReadWrite" which are unwelcome here
+                // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method.
+
+                if (TryConvertToPoolBlockingPeriod(sValue, out result))
+                {
+                    return result;
+                }
+
+                // try again after remove leading & trailing whitespaces.
+                sValue = sValue.Trim();
+                if (TryConvertToPoolBlockingPeriod(sValue, out result))
+                {
+                    return result;
+                }
+
+                // string values must be valid
+                throw ADP.InvalidConnectionOptionValue(keyword);
+            }
+            else
+            {
+                // the value is not string, try other options
+                PoolBlockingPeriod eValue;
+
+                if (value is PoolBlockingPeriod)
+                {
+                    // quick path for the most common case
+                    eValue = (PoolBlockingPeriod)value;
+                }
+                else if (value.GetType().IsEnum)
+                {
+                    // explicitly block scenarios in which user tries to use wrong enum types, like:
+                    // builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process;
+                    // workaround: explicitly cast non-PoolBlockingPeriod enums to int
+                    throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null);
+                }
+                else
+                {
+                    try
+                    {
+                        // Enum.ToObject allows only integral and enum values (enums are blocked above), rasing ArgumentException for the rest
+                        eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value);
+                    }
+                    catch (ArgumentException e)
+                    {
+                        // to be consistent with the messages we send in case of wrong type usage, replace 
+                        // the error with our exception, and keep the original one as inner one for troubleshooting
+                        throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e);
+                    }
+                }
+
+                // ensure value is in valid range
+                if (IsValidPoolBlockingPeriodValue(eValue))
+                {
+                    return eValue;
+                }
+                else
+                {
+                    throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue);
+                }
+            }
+        }
+        #endregion
+
         const string ApplicationIntentReadWriteString = "ReadWrite";
         const string ApplicationIntentReadOnlyString = "ReadOnly";
 
@@ -752,6 +889,7 @@ namespace System.Data.Common {
                internal const int    ConnectRetryInterval           = 10;
         internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified;
         internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
+        internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto;
     }
 
     internal static class DbConnectionOptionKeywords {
@@ -819,6 +957,7 @@ namespace System.Data.Common {
                internal const string Authentication                 = "Authentication";
                internal const string Certificate                    = "Certificate";
                internal const string ColumnEncryptionSetting        = "Column Encryption Setting";
+        internal const string PoolBlockingPeriod             = "PoolBlockingPeriod";
         
         // common keywords (OleDb, OracleClient, SqlClient)
         internal const string DataSource                = "Data Source";
index cb0c072a6596823dda1c71424cf7f7567719a28b..44d81f07e1ef51520c0677f750ff35d1e6774efc 100644 (file)
@@ -2122,7 +2122,12 @@ namespace System.Data {
             if (stream == null)
                 return XmlReadMode.Auto;
 
-            return ReadXml(new XmlTextReader(stream), false);
+            XmlTextReader xr = new XmlTextReader(stream);
+
+            // Prevent Dtd entity in dataset 
+            xr.XmlResolver = null;
+
+            return ReadXml(xr, false);
         }
 
         /// <devdoc>
@@ -2132,7 +2137,12 @@ namespace System.Data {
             if (reader == null)
                 return XmlReadMode.Auto;
 
-            return ReadXml(new XmlTextReader(reader), false);
+            XmlTextReader xr = new XmlTextReader(reader);
+
+            // Prevent Dtd entity in dataset 
+            xr.XmlResolver = null;
+
+            return ReadXml(xr, false);
         }
 
         /// <devdoc>
@@ -2142,7 +2152,12 @@ namespace System.Data {
         public XmlReadMode ReadXml(string fileName)
         {
             XmlTextReader xr = new XmlTextReader(fileName);
-            try {
+
+            // Prevent Dtd entity in dataset 
+            xr.XmlResolver = null;
+
+            try
+            {
                 return ReadXml(xr, false);
             }
             finally {
@@ -2520,6 +2535,8 @@ namespace System.Data {
                 return XmlReadMode.Auto;
 
             XmlTextReader reader = (mode == XmlReadMode.Fragment) ? new XmlTextReader(stream, XmlNodeType.Element, null) : new XmlTextReader(stream);
+            // Prevent Dtd entity in dataset 
+            reader.XmlResolver = null;
             return ReadXml(reader, mode, false);
         }
 
@@ -2531,6 +2548,8 @@ namespace System.Data {
                 return XmlReadMode.Auto;
 
             XmlTextReader xmlreader = (mode == XmlReadMode.Fragment) ? new XmlTextReader(reader.ReadToEnd(), XmlNodeType.Element, null) : new XmlTextReader(reader);
+            // Prevent Dtd entity in dataset 
+            xmlreader.XmlResolver = null;
             return ReadXml(xmlreader, mode, false);
         }
 
@@ -2547,7 +2566,12 @@ namespace System.Data {
             }
             else
                 xr = new XmlTextReader(fileName);
-            try {
+
+            // Prevent Dtd entity in dataset             
+            xr.XmlResolver = null;
+
+            try
+            {
                 return ReadXml(xr, mode, false);
             }
             finally {
index 637816ef0c379f684e5e1133aca1e168b9896e41..24673fa5c5120d868cf61c9ab74da5abe2261022 100644 (file)
@@ -5044,7 +5044,12 @@ namespace System.Data {
             if (stream == null)
                 return XmlReadMode.Auto;
 
-            return ReadXml( new XmlTextReader(stream), false);
+            XmlTextReader xr = new XmlTextReader(stream);
+
+            // Prevent Dtd entity in DataTable 
+            xr.XmlResolver = null;
+
+            return ReadXml(xr, false);
         }
 
         public XmlReadMode ReadXml(TextReader reader)
@@ -5052,7 +5057,12 @@ namespace System.Data {
             if (reader == null)
                 return XmlReadMode.Auto;
 
-            return ReadXml( new XmlTextReader(reader), false);
+            XmlTextReader xr = new XmlTextReader(reader);
+
+            // Prevent Dtd entity in DataTable 
+            xr.XmlResolver = null;
+
+            return ReadXml(xr, false);
         }
 
         [ResourceExposure(ResourceScope.Machine)]
@@ -5060,7 +5070,12 @@ namespace System.Data {
         public XmlReadMode ReadXml(string fileName)
         {
             XmlTextReader xr = new XmlTextReader(fileName);
-            try {
+
+            // Prevent Dtd entity in DataTable 
+            xr.XmlResolver = null;
+
+            try
+            {
                 return ReadXml( xr , false);
             }
             finally {
index 5b5743725f9af7606751f7ce84d20a29cabc57f5..dd0b6ad4bb3057b466d8c29e752c5ad1745a8a80 100644 (file)
@@ -12,6 +12,7 @@ namespace System.Data.ProviderBase {
     using System.Collections;
     using System.Collections.Generic;
     using System.Data.Common;
+    using System.Data.SqlClient;
     using System.Diagnostics;
     using System.Globalization;
     using System.Runtime.CompilerServices;
@@ -756,7 +757,81 @@ namespace System.Data.ProviderBase {
         private Timer CreateCleanupTimer() {
             return (new Timer(new TimerCallback(this.CleanupCallback), null, _cleanupWait, _cleanupWait));
         }
-        
+
+        private static readonly string[] AzureSqlServerEndpoints = {Res.GetString(Res.AZURESQL_GenericEndpoint),
+                                                                    Res.GetString(Res.AZURESQL_GermanEndpoint),
+                                                                    Res.GetString(Res.AZURESQL_UsGovEndpoint),
+                                                                    Res.GetString(Res.AZURESQL_ChinaEndpoint) };
+        private static bool IsAzureSqlServerEndpoint(string dataSource)
+        {
+            // remove server port
+            var i = dataSource.LastIndexOf(',');
+            if (i >= 0)
+            {
+                dataSource = dataSource.Substring(0, i);
+            }
+
+            // check for the instance name
+            i = dataSource.LastIndexOf('\\');
+            if (i >= 0)
+            {
+                dataSource = dataSource.Substring(0, i);
+            }
+
+            // trim redundant whitespaces
+            dataSource = dataSource.Trim();
+
+            // check if servername end with any azure endpoints
+            for (i = 0; i < AzureSqlServerEndpoints.Length; i++)
+            {
+                if (dataSource.EndsWith(AzureSqlServerEndpoints[i], StringComparison.OrdinalIgnoreCase))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private bool IsBlockingPeriodEnabled()
+        {
+            var poolGroupConnectionOptions = _connectionPoolGroup.ConnectionOptions as SqlConnectionString;
+            if (poolGroupConnectionOptions == null)
+            {
+                return true;
+            }
+
+            var policy = poolGroupConnectionOptions.PoolBlockingPeriod;
+
+            switch (policy)
+            {
+                case PoolBlockingPeriod.Auto:
+                {
+                    if (IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource))
+                    {
+                        return false; // in Azure it will be Disabled
+                    }
+                    else
+                    {
+                        return true; // in Non Azure, it will be Enabled
+                    }
+                }
+                case PoolBlockingPeriod.AlwaysBlock:
+                {
+                    return true; //Enabled
+                }
+                case PoolBlockingPeriod.NeverBlock:
+                {
+                    return false; //Disabled
+                }
+                default:
+                {
+                    //we should never get into this path.
+                    Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement.");
+                    return true;
+                }
+            }
+        }
+
         private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) {
             DbConnectionInternal newObj = null;
 
@@ -797,7 +872,7 @@ namespace System.Data.ProviderBase {
                 // Reset the error wait:
                 _errorWait = ERROR_WAIT_DEFAULT;
             }
-            catch(Exception e)  {
+            catch(Exception e)   {
                 // 
                 if (!ADP.IsCatchableExceptionType(e)) {
                     throw;
@@ -805,6 +880,11 @@ namespace System.Data.ProviderBase {
 
                 ADP.TraceExceptionForCapture(e);
 
+                if (!IsBlockingPeriodEnabled())
+                {
+                    throw;
+                }
+
                 newObj = null; // set to null, so we do not return bad new object
                 // Failed to create instance
                 _resError = e;
index 112108ae14bf73a2c6258526477d51829460271a..501ed7c91507a590976492fe4f1e503dafe62207 100644 (file)
@@ -15,10 +15,9 @@ namespace System.Data.SqlClient
     /// Base class containing raw key bytes for symmetric key algorithms. Some encryption algorithms can use the key directly while others derive sub keys from this.
     /// If an algorithm needs to derive more keys, have a derived class from this and use it in the corresponding encryption algorithm.
     /// </summary>
-    internal class SqlClientSymmetricKey
-    {
+    internal class SqlClientSymmetricKey {
         /// <summary>
-        /// DPAPI protected key
+        /// The underlying key material
         /// </summary>
         protected readonly byte[] _rootKey;
 
@@ -26,8 +25,7 @@ namespace System.Data.SqlClient
         /// Constructor that initializes the root key.
         /// </summary>
         /// <param name="rootKey">root key</param>
-        internal SqlClientSymmetricKey(byte[] rootKey)
-        {
+        internal SqlClientSymmetricKey(byte[] rootKey) {
             // Key validation
             if (rootKey == null || rootKey.Length == 0) {
                 throw SQL.NullColumnEncryptionKeySysErr();
@@ -36,14 +34,24 @@ namespace System.Data.SqlClient
             _rootKey = rootKey;
         }
 
+        /// <summary>
+        /// Destructor that cleans up the key material.
+        /// This is a best effort approach since there are no guarantees around GC.
+        /// </summary>
+        ~SqlClientSymmetricKey() {
+            if (_rootKey != null) {
+                for (int i = 0; i < _rootKey.Length; i++) {
+                    _rootKey[i] = 0;
+                }
+            }
+        }
+
         /// <summary>
         /// Returns a copy of the plain text key
         /// This is needed for actual encryption/decryption.
         /// </summary>
-        internal virtual byte[] RootKey
-        {
-            get 
-            {
+        internal virtual byte[] RootKey {
+            get {
                 return _rootKey; 
             }
         }
@@ -52,8 +60,7 @@ namespace System.Data.SqlClient
         /// Computes SHA256 value of the plain text key bytes
         /// </summary>
         /// <returns>A string containing SHA256 hash of the root key</returns>
-        internal virtual string GetKeyHash()
-        {
+        internal virtual string GetKeyHash() {
             return SqlSecurityUtility.GetSHA256Hash(RootKey);
         }
 
@@ -63,10 +70,7 @@ namespace System.Data.SqlClient
         /// <returns>
         /// Returns the length of the root key
         /// </returns>
-        internal virtual int Length()
-        {
-            // Note: DPAPI preserves the original byte length
-            // so for now, this is as same as returning the length of the raw key.
+        internal virtual int Length() {
             return _rootKey.Length;
         }
     }
index 2e560dbf344a2a5ef4577863f3342dc13d2498de..46a53537089cdd872b7c8964bfc4fc8718f9c782 100644 (file)
@@ -81,7 +81,12 @@ namespace System.Data.SqlClient {
         /// Force the client to sleep during sp_describe_parameter_encryption after ReadDescribeEncryptionParameterResults.
         /// </summary>
         private static bool _sleepAfterReadDescribeEncryptionParameterResults = false;
-#endif
+
+        /// <summary>
+        /// Internal flag for testing purposes that forces all queries to internally end async calls.
+        /// </summary>
+        private static bool _forceInternalEndQuery = false;
+#endif 
 
         // devnote: Prepare
         // Against 7.0 Server (Sphinx) a prepare/unprepare requires an extra roundtrip to the server.
@@ -287,6 +292,16 @@ namespace System.Data.SqlClient {
             }
         }
 
+        /// <summary>
+        /// A flag to indicate if EndExecute was already initiated by the Begin call.
+        /// </summary>
+        private volatile bool _internalEndExecuteInitiated;
+
+        /// <summary>
+        /// A flag to indicate whether we postponed caching the query metadata for this command.
+        /// </summary>
+        internal bool CachingQueryMetadataPostponed { get; set; }
+
         //
         //  Smi execution-specific stuff
         //
@@ -1170,7 +1185,8 @@ namespace System.Data.SqlClient {
             try {
                 statistics = SqlStatistics.StartTimer(Statistics);
                 WriteBeginExecuteEvent();
-                InternalExecuteNonQuery(null, ADP.ExecuteNonQuery, false, CommandTimeout);
+                bool usedCache;
+                InternalExecuteNonQuery(null, ADP.ExecuteNonQuery, false, CommandTimeout, out usedCache);
                 success = true;
                 return _rowsAffected;
             }
@@ -1199,7 +1215,8 @@ namespace System.Data.SqlClient {
             Bid.ScopeEnter(out hscp, "<sc.SqlCommand.ExecuteToPipe|INFO> %d#", ObjectID);
             try {
                 statistics = SqlStatistics.StartTimer(Statistics);
-                InternalExecuteNonQuery(null, ADP.ExecuteNonQuery, true, CommandTimeout);
+                bool usedCache;
+                InternalExecuteNonQuery(null, ADP.ExecuteNonQuery, true, CommandTimeout, out usedCache);
             }
             finally {
                 SqlStatistics.StopTimer(statistics);
@@ -1217,34 +1234,41 @@ namespace System.Data.SqlClient {
         public IAsyncResult BeginExecuteNonQuery(AsyncCallback callback, object stateObject) {
             Bid.CorrelationTrace("<sc.SqlCommand.BeginExecuteNonQuery|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
             SqlConnection.ExecutePermission.Demand();
-            return BeginExecuteNonQueryInternal(callback, stateObject, 0);
+            return BeginExecuteNonQueryInternal(0, callback, stateObject, 0, inRetry: false);
         }
 
         private IAsyncResult BeginExecuteNonQueryAsync(AsyncCallback callback, object stateObject) {
-            return BeginExecuteNonQueryInternal(callback, stateObject, CommandTimeout, asyncWrite:true);
+            return BeginExecuteNonQueryInternal(0, callback, stateObject, CommandTimeout, inRetry: false, asyncWrite:true);
         }
 
-        private IAsyncResult BeginExecuteNonQueryInternal(AsyncCallback callback, object stateObject, int timeout, bool asyncWrite = false) {
-            // Reset _pendingCancel upon entry into any Execute - used to synchronize state
-            // between entry into Execute* API and the thread obtaining the stateObject.
-            _pendingCancel = false;
+        private IAsyncResult BeginExecuteNonQueryInternal(CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite = false) {
+            TaskCompletionSource<object> globalCompletion = new TaskCompletionSource<object>(stateObject);
+            TaskCompletionSource<object> localCompletion = new TaskCompletionSource<object>(stateObject);
+
+            if (!inRetry) {
+                // Reset _pendingCancel upon entry into any Execute - used to synchronize state
+                // between entry into Execute* API and the thread obtaining the stateObject.
+                _pendingCancel = false;
+
+                ValidateAsyncCommand(); // Special case - done outside of try/catches to prevent putting a stateObj
+                                        // back into pool when we should not.
+            }
 
-            ValidateAsyncCommand(); // Special case - done outside of try/catches to prevent putting a stateObj
-                                    // back into pool when we should not.
-            
             SqlStatistics statistics = null;
             try {
-                statistics = SqlStatistics.StartTimer(Statistics);
-                WriteBeginExecuteEvent();
-                TaskCompletionSource<object> completion = new TaskCompletionSource<object>(stateObject);
+                if (!inRetry) {
+                    statistics = SqlStatistics.StartTimer(Statistics);
+                    WriteBeginExecuteEvent();
+                }
 
+                bool usedCache;
                 try { // InternalExecuteNonQuery already has reliability block, but if failure will not put stateObj back into pool.
-                    Task execNQ = InternalExecuteNonQuery(completion, ADP.BeginExecuteNonQuery, false, timeout, asyncWrite);
+                    Task execNQ = InternalExecuteNonQuery(localCompletion, ADP.BeginExecuteNonQuery, false, timeout, out usedCache, asyncWrite, inRetry: inRetry);
                     if (execNQ != null) {
-                        AsyncHelper.ContinueTask(execNQ, completion, () => BeginExecuteNonQueryInternalReadStage(completion));
+                        AsyncHelper.ContinueTask(execNQ, localCompletion, () => BeginExecuteNonQueryInternalReadStage(localCompletion));
                     }
                     else {
-                        BeginExecuteNonQueryInternalReadStage(completion);
+                        BeginExecuteNonQueryInternalReadStage(localCompletion);
                     }
                 }
                 catch (Exception e) {
@@ -1258,12 +1282,18 @@ namespace System.Data.SqlClient {
                     throw;
                 }
 
+                // When we use query caching for parameter encryption we need to retry on specific errors.
+                // In these cases finalize the call internally and trigger a retry when needed.
+                if (!TriggerInternalEndAndRetryIfNecessary(behavior, stateObject, timeout, ADP.EndExecuteNonQuery, usedCache, inRetry, asyncWrite, globalCompletion, localCompletion, InternalEndExecuteNonQuery, BeginExecuteNonQueryInternal)) {
+                    globalCompletion = localCompletion;
+                }
+
                 // Add callback after work is done to avoid overlapping Begin\End methods
                 if (callback != null) {
-                    completion.Task.ContinueWith((t) => callback(t), TaskScheduler.Default);
+                    globalCompletion.Task.ContinueWith((t) => callback(t), TaskScheduler.Default);
                 }
 
-                return completion.Task;
+                return globalCompletion.Task;
             }
             finally {
                 SqlStatistics.StopTimer(statistics);
@@ -1319,7 +1349,7 @@ namespace System.Data.SqlClient {
             }
         }
 
-        private void VerifyEndExecuteState(Task completionTask, String endMethod) {
+        private void VerifyEndExecuteState(Task completionTask, String endMethod, bool fullCheckForColumnEncryption = false) {
             if (null == completionTask) {
                 throw ADP.ArgumentNull("asyncResult");
             }
@@ -1340,7 +1370,7 @@ namespace System.Data.SqlClient {
 
             // If transparent parameter encryption was attempted, then we need to skip other checks like those on EndMethodName
             // since we want to wait for async results before checking those fields.
-            if (IsColumnEncryptionEnabled) {
+            if (IsColumnEncryptionEnabled && !fullCheckForColumnEncryption) {
                 if (_activeConnection.State != ConnectionState.Open) {
                     // If the connection is not 'valid' then it was closed while we were executing
                     throw ADP.ClosedConnectionError();
@@ -1361,13 +1391,24 @@ namespace System.Data.SqlClient {
             }
         }
 
-        private void WaitForAsyncResults(IAsyncResult asyncResult) {
+        private void WaitForAsyncResults(IAsyncResult asyncResult, bool isInternal) {
             Task completionTask = (Task) asyncResult;
             if (!asyncResult.IsCompleted) {
                 asyncResult.AsyncWaitHandle.WaitOne();
             }
-            _stateObj._networkPacketTaskSource = null;
-            _activeConnection.GetOpenTdsConnection().DecrementAsyncCount();
+
+            if (_stateObj != null) {
+                _stateObj._networkPacketTaskSource = null;
+            }
+
+            // If this is an internal command we will decrement the count when the End method is actually called by the user.
+            // If we are using Column Encryption and the previous task failed, the async count should have already been fixed up. 
+            // There is a generic issue in how we handle the async count because:
+            // a) BeginExecute might or might not clean it up on failure.
+            // b) In EndExecute, we check the task state before waiting and throw if it's failed, whereas if we wait we will always adjust the count.
+            if (!isInternal && (!IsColumnEncryptionEnabled || !completionTask.IsFaulted)) {
+                _activeConnection.GetOpenTdsConnection().DecrementAsyncCount();
+            }
         }
 
         public int EndExecuteNonQuery(IAsyncResult asyncResult) {
@@ -1390,6 +1431,7 @@ namespace System.Data.SqlClient {
         
         private int EndExecuteNonQueryAsync(IAsyncResult asyncResult) {
             Bid.CorrelationTrace("<sc.SqlCommand.EndExecuteNonQueryAsync|Info|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
+            Debug.Assert(!_internalEndExecuteInitiated || _stateObj == null);
 
             Exception asyncException = ((Task)asyncResult).Exception;
             if (asyncException != null) {
@@ -1400,7 +1442,13 @@ namespace System.Data.SqlClient {
             else {
                 ThrowIfReconnectionHasBeenCanceled();
                 // lock on _stateObj prevents ----s with close/cancel.
-                lock (_stateObj) {
+                // If we have already initiate the End call internally, we have already done that, so no point doing it again.
+                if (!_internalEndExecuteInitiated) {
+                    lock (_stateObj) {
+                        return EndExecuteNonQueryInternal(asyncResult);
+                    }
+                }
+                else {
                     return EndExecuteNonQueryInternal(asyncResult);
                 }
             }
@@ -1408,11 +1456,43 @@ namespace System.Data.SqlClient {
 
         private int EndExecuteNonQueryInternal(IAsyncResult asyncResult) {
             SqlStatistics statistics = null;
+            bool success = false;
+            int? sqlExceptionNumber = null;
+            try {
+                statistics = SqlStatistics.StartTimer(Statistics);
+                int result = (int)InternalEndExecuteNonQuery(asyncResult, ADP.EndExecuteNonQuery, isInternal: false);
+                success = true;
+                return result;
+            }
+            catch (SqlException e) {
+                sqlExceptionNumber = e.Number;
+                if (cachedAsyncState != null) {
+                    cachedAsyncState.ResetAsyncState();
+                };
 
+                //  SqlException is always catchable 
+                ReliablePutStateObject();
+                throw;
+            }
+            catch (Exception e) {
+                if (cachedAsyncState != null) {
+                    cachedAsyncState.ResetAsyncState();
+                };
+                if (ADP.IsCatchableExceptionType(e)) {
+                    ReliablePutStateObject();
+                };
+                throw;
+            }
+            finally {
+                SqlStatistics.StopTimer(statistics);
+                WriteEndExecuteEvent(success, sqlExceptionNumber, synchronous: false);
+            }
+        }
+
+        private object InternalEndExecuteNonQuery(IAsyncResult asyncResult, string endMethod, bool isInternal) {
             TdsParser bestEffortCleanupTarget = null;
             RuntimeHelpers.PrepareConstrainedRegions();
-            bool success = false;
-            int? sqlExceptionNumber = null;
+
             try {
 #if DEBUG
                 TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection();
@@ -1424,30 +1504,32 @@ namespace System.Data.SqlClient {
                 {
 #endif //DEBUG
                     bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(_activeConnection);
-                    statistics = SqlStatistics.StartTimer(Statistics);
-                    VerifyEndExecuteState((Task)asyncResult, ADP.EndExecuteNonQuery);
-                    WaitForAsyncResults(asyncResult);
+                    VerifyEndExecuteState((Task)asyncResult, endMethod);
+                    WaitForAsyncResults(asyncResult, isInternal);
 
-                    // If Transparent parameter encryption was attempted, then we would have skipped the below 
-                    // checks in VerifyEndExecuteState since we wanted to wait for WaitForAsyncResults to complete.
+                    // If column encryption is enabled, also check the state after waiting for the task.
+                    // It would be better to do this for all cases, but avoiding for compatibility reasons.
                     if (IsColumnEncryptionEnabled) {
-                        if (cachedAsyncState.EndMethodName == null) {
-                            throw ADP.MethodCalledTwice(ADP.EndExecuteNonQuery);
-                        }
-
-                        if (ADP.EndExecuteNonQuery != cachedAsyncState.EndMethodName) {
-                            throw ADP.MismatchedAsyncResult(cachedAsyncState.EndMethodName, ADP.EndExecuteNonQuery);
-                        }
-
-                        if (!cachedAsyncState.IsActiveConnectionValid(_activeConnection)) {
-                            // If the connection is not 'valid' then it was closed while we were executing
-                            throw ADP.ClosedConnectionError();
-                        }
+                        VerifyEndExecuteState((Task)asyncResult, endMethod, fullCheckForColumnEncryption: true);
                     }
 
                     bool processFinallyBlock = true;
                     try {
-                        NotifyDependency();
+                        // If this is not for internal usage, notify the dependency. 
+                        // If we have already initiated the end internally, the reader should be ready, so just return the rows affected.
+                        if (!isInternal) {
+                            NotifyDependency();
+
+                            if (_internalEndExecuteInitiated) {
+                                Debug.Assert(_stateObj == null);
+
+                                // Reset the state since we exit early.
+                                cachedAsyncState.ResetAsyncState();
+
+                                return _rowsAffected;
+                            }
+                        }
+
                         CheckThrowSNIException();
 
                         // only send over SQL Batch command if we are not a stored proc and have no parameters
@@ -1459,20 +1541,19 @@ namespace System.Data.SqlClient {
                                 if (!result) { throw SQL.SynchronousCallMayNotPend(); }
                             }
                             finally {
-                                cachedAsyncState.ResetAsyncState();
+                                // Don't reset the state for internal End. The user End will do that eventually.
+                                if (!isInternal) {
+                                    cachedAsyncState.ResetAsyncState();
+                                }
                             }
                         }
                         else { // otherwise, use a full-fledged execute that can handle params and stored procs
-                            SqlDataReader reader = CompleteAsyncExecuteReader();
+                            SqlDataReader reader = CompleteAsyncExecuteReader(isInternal);
                             if (null != reader) {
                                 reader.Close();
                             }
                         }
                     }
-                    catch (SqlException e) {
-                        sqlExceptionNumber = e.Number;
-                        throw;
-                    }
                     catch (Exception e) {
                         processFinallyBlock = ADP.IsCatchableExceptionType(e);
                         throw;
@@ -1484,7 +1565,6 @@ namespace System.Data.SqlClient {
                     }
 
                     Debug.Assert(null == _stateObj, "non-null state object in EndExecuteNonQuery");
-                    success = true;
                     return _rowsAffected;
                 }
 #if DEBUG
@@ -1506,23 +1586,11 @@ namespace System.Data.SqlClient {
                 SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget);
                 throw;
             }
-            catch (Exception e) {
-                if (cachedAsyncState != null) {
-                    cachedAsyncState.ResetAsyncState();
-                };
-                if (ADP.IsCatchableExceptionType(e)) {
-                    ReliablePutStateObject();
-                };
-                throw;
-            }
-            finally {
-                SqlStatistics.StopTimer(statistics);
-                WriteEndExecuteEvent(success, sqlExceptionNumber, synchronous: false);
-            }
         }
 
-        private Task InternalExecuteNonQuery(TaskCompletionSource<object> completion, string methodName, bool sendToPipe, int timeout, bool asyncWrite = false) {
+        private Task InternalExecuteNonQuery(TaskCompletionSource<object> completion, string methodName, bool sendToPipe, int timeout, out bool usedCache, bool asyncWrite = false, bool inRetry = false) {
             bool async = (null != completion);
+            usedCache = false;
 
             SqlStatistics statistics = Statistics;
             _rowsAffected = -1;
@@ -1542,7 +1610,9 @@ namespace System.Data.SqlClient {
                     bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(_activeConnection);
                     // @devnote: this function may throw for an invalid connection
                     // @devnote: returns false for empty command text
-                    ValidateCommand(methodName, async);
+                    if (!inRetry) {
+                        ValidateCommand(methodName, async);
+                    }
                     CheckNotificationStateAndAutoEnlist(); // Only call after validate - requires non null connection!
 
                     Task task = null;
@@ -1566,12 +1636,15 @@ namespace System.Data.SqlClient {
                             }
                         }
 
+                        // We should never get here for a retry since we only have retries for parameters.
+                        Debug.Assert(!inRetry);
+
                         task = RunExecuteNonQueryTds(methodName, async, timeout, asyncWrite);
                     }
                     else  { // otherwise, use a full-fledged execute that can handle params and stored procs
                         Debug.Assert( !sendToPipe, "trying to send non-context command to pipe" );
                         Bid.Trace("<sc.SqlCommand.ExecuteNonQuery|INFO> %d#, Command executed as RPC.\n", ObjectID);
-                        SqlDataReader reader = RunExecuteReader(0, RunBehavior.UntilDone, false, methodName, completion, timeout, out task, asyncWrite);
+                        SqlDataReader reader = RunExecuteReader(0, RunBehavior.UntilDone, false, methodName, completion, timeout, out task, out usedCache, asyncWrite, inRetry);
                         if (null!=reader) {
                             if (task != null) {
                                 task = AsyncHelper.CreateContinuationTask(task, () => reader.Close());
@@ -1649,31 +1722,38 @@ namespace System.Data.SqlClient {
         [System.Security.Permissions.HostProtectionAttribute(ExternalThreading=true)]
         public IAsyncResult BeginExecuteXmlReader(AsyncCallback callback, object stateObject) {
             Bid.CorrelationTrace("<sc.SqlCommand.BeginExecuteXmlReader|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
-            SqlConnection.ExecutePermission.Demand();   
-            return BeginExecuteXmlReaderInternal(callback, stateObject, 0);
+            SqlConnection.ExecutePermission.Demand();
+            return BeginExecuteXmlReaderInternal(CommandBehavior.SequentialAccess, callback, stateObject, 0, inRetry: false);
         }
 
         private IAsyncResult BeginExecuteXmlReaderAsync(AsyncCallback callback, object stateObject) {
-            return BeginExecuteXmlReaderInternal(callback, stateObject, CommandTimeout, asyncWrite:true);
+            return BeginExecuteXmlReaderInternal(CommandBehavior.SequentialAccess, callback, stateObject, CommandTimeout, inRetry: false, asyncWrite: true);
         }
 
-        private IAsyncResult BeginExecuteXmlReaderInternal(AsyncCallback callback, object stateObject, int timeout, bool asyncWrite = false) {        
-            // Reset _pendingCancel upon entry into any Execute - used to synchronize state
-            // between entry into Execute* API and the thread obtaining the stateObject.
-            _pendingCancel = false;
+        private IAsyncResult BeginExecuteXmlReaderInternal(CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite = false) {
+            TaskCompletionSource<object> globalCompletion = new TaskCompletionSource<object>(stateObject);
+            TaskCompletionSource<object> localCompletion = new TaskCompletionSource<object>(stateObject);
 
-            ValidateAsyncCommand(); // Special case - done outside of try/catches to prevent putting a stateObj
-                                    // back into pool when we should not.
+            if (!inRetry) {
+                // Reset _pendingCancel upon entry into any Execute - used to synchronize state
+                // between entry into Execute* API and the thread obtaining the stateObject.
+                _pendingCancel = false;
+
+                ValidateAsyncCommand(); // Special case - done outside of try/catches to prevent putting a stateObj
+                                        // back into pool when we should not.
+            }
 
             SqlStatistics statistics = null;
             try {
-                statistics = SqlStatistics.StartTimer(Statistics);
-                WriteBeginExecuteEvent();
-                TaskCompletionSource<object> completion = new TaskCompletionSource<object>(stateObject);
+                if (!inRetry) {
+                    statistics = SqlStatistics.StartTimer(Statistics);
+                    WriteBeginExecuteEvent();
+                }
 
+                bool usedCache;
                 Task writeTask;
                 try { // InternalExecuteNonQuery already has reliability block, but if failure will not put stateObj back into pool.
-                    RunExecuteReader(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, true, ADP.BeginExecuteXmlReader, completion, timeout, out writeTask, asyncWrite);
+                    RunExecuteReader(behavior, RunBehavior.ReturnImmediately, true, ADP.BeginExecuteXmlReader, localCompletion, timeout, out writeTask, out usedCache, asyncWrite, inRetry);
                 }
                 catch (Exception e) {
                     if (!ADP.IsCatchableOrSecurityExceptionType(e)) {
@@ -1687,17 +1767,23 @@ namespace System.Data.SqlClient {
                 }
 
                 if (writeTask != null) {
-                    AsyncHelper.ContinueTask(writeTask, completion, () => BeginExecuteXmlReaderInternalReadStage(completion));
+                    AsyncHelper.ContinueTask(writeTask, localCompletion, () => BeginExecuteXmlReaderInternalReadStage(localCompletion));
                 }
                 else {
-                    BeginExecuteXmlReaderInternalReadStage(completion);
+                    BeginExecuteXmlReaderInternalReadStage(localCompletion);
+                }
+
+                // When we use query caching for parameter encryption we need to retry on specific errors.
+                // In these cases finalize the call internally and trigger a retry when needed.
+                if (!TriggerInternalEndAndRetryIfNecessary(behavior, stateObject, timeout, ADP.EndExecuteXmlReader, usedCache, inRetry, asyncWrite, globalCompletion, localCompletion, InternalEndExecuteReader, BeginExecuteXmlReaderInternal)) {
+                    globalCompletion = localCompletion;
                 }
 
                 // Add callback after work is done to avoid overlapping Begin\End methods
                 if (callback != null) {
-                    completion.Task.ContinueWith((t) => callback(t), TaskScheduler.Default);
+                    globalCompletion.Task.ContinueWith((t) => callback(t), TaskScheduler.Default);
                 }
-                return completion.Task;
+                return globalCompletion.Task;
             }
             finally {
                 SqlStatistics.StopTimer(statistics);
@@ -1768,6 +1854,7 @@ namespace System.Data.SqlClient {
 
         private XmlReader EndExecuteXmlReaderAsync(IAsyncResult asyncResult) {
             Bid.CorrelationTrace("<sc.SqlCommand.EndExecuteXmlReaderAsync|Info|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
+            Debug.Assert(!_internalEndExecuteInitiated || _stateObj == null);
 
             Exception asyncException = ((Task)asyncResult).Exception;
             if (asyncException != null) {
@@ -1778,7 +1865,13 @@ namespace System.Data.SqlClient {
             else {
                 ThrowIfReconnectionHasBeenCanceled();
                 // lock on _stateObj prevents ----s with close/cancel.
-                lock (_stateObj) {
+                // If we have already initiate the End call internally, we have already done that, so no point doing it again.
+                if (!_internalEndExecuteInitiated) {
+                    lock (_stateObj) {
+                        return EndExecuteXmlReaderInternal(asyncResult);
+                    }
+                }
+                else {
                     return EndExecuteXmlReaderInternal(asyncResult);
                 }
             }
@@ -1788,7 +1881,7 @@ namespace System.Data.SqlClient {
             bool success = false;
             int? sqlExceptionNumber = null;
             try {
-                XmlReader result = CompleteXmlReader(InternalEndExecuteReader(asyncResult, ADP.EndExecuteXmlReader));
+                XmlReader result = CompleteXmlReader(InternalEndExecuteReader(asyncResult, ADP.EndExecuteXmlReader, isInternal: false));
                 success = true;
                 return result;
             }
@@ -1894,7 +1987,7 @@ namespace System.Data.SqlClient {
         public IAsyncResult BeginExecuteReader(AsyncCallback callback, object stateObject, CommandBehavior behavior) {
             Bid.CorrelationTrace("<sc.SqlCommand.BeginExecuteReader|API|Correlation> ObjectID%d#, behavior=%d{ds.CommandBehavior}, ActivityID %ls\n", ObjectID, (int)behavior);
             SqlConnection.ExecutePermission.Demand();
-            return BeginExecuteReaderInternal(behavior, callback, stateObject, 0);
+            return BeginExecuteReaderInternal(behavior, callback, stateObject, 0, inRetry: false);
         }
 
         internal SqlDataReader ExecuteReader(CommandBehavior behavior, string method) {
@@ -1967,6 +2060,7 @@ namespace System.Data.SqlClient {
 
         private SqlDataReader EndExecuteReaderAsync(IAsyncResult asyncResult) {
             Bid.CorrelationTrace("<sc.SqlCommand.EndExecuteReaderAsync|Info|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
+            Debug.Assert(!_internalEndExecuteInitiated || _stateObj == null);
 
             Exception asyncException = ((Task)asyncResult).Exception;
             if (asyncException != null) {
@@ -1977,8 +2071,14 @@ namespace System.Data.SqlClient {
             else {
                 ThrowIfReconnectionHasBeenCanceled();
                 // lock on _stateObj prevents ----s with close/cancel.
-                lock (_stateObj) {
+                // If we have already initiate the End call internally, we have already done that, so no point doing it again.
+                if (!_internalEndExecuteInitiated) {
+                    lock (_stateObj) {
                         return EndExecuteReaderInternal(asyncResult);
+                    }
+                }
+                else {
+                    return EndExecuteReaderInternal(asyncResult);
                 }
             }
         }
@@ -1989,7 +2089,7 @@ namespace System.Data.SqlClient {
             int? sqlExceptionNumber = null;
             try {
                 statistics = SqlStatistics.StartTimer(Statistics);
-                SqlDataReader result = InternalEndExecuteReader(asyncResult, ADP.EndExecuteReader);
+                SqlDataReader result = InternalEndExecuteReader(asyncResult, ADP.EndExecuteReader, isInternal: false);
                 success = true;
                 return result;
             }
@@ -2020,26 +2120,33 @@ namespace System.Data.SqlClient {
         }
 
         private IAsyncResult BeginExecuteReaderAsync(CommandBehavior behavior, AsyncCallback callback, object stateObject) {
-            return BeginExecuteReaderInternal(behavior, callback, stateObject, CommandTimeout, asyncWrite:true);
+            return BeginExecuteReaderInternal(behavior, callback, stateObject, CommandTimeout, inRetry: false, asyncWrite:true);
         }
 
-        private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool asyncWrite = false) {        
-            // Reset _pendingCancel upon entry into any Execute - used to synchronize state
-            // between entry into Execute* API and the thread obtaining the stateObject.
-            _pendingCancel = false;
+        private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite = false) {
+            TaskCompletionSource<object> globalCompletion = new TaskCompletionSource<object>(stateObject);
+            TaskCompletionSource<object> localCompletion = new TaskCompletionSource<object>(stateObject);
+
+            if (!inRetry) {
+                // Reset _pendingCancel upon entry into any Execute - used to synchronize state
+                // between entry into Execute* API and the thread obtaining the stateObject.
+                _pendingCancel = false;
+            }
 
             SqlStatistics statistics = null;
             try {
-                statistics = SqlStatistics.StartTimer(Statistics);
-                WriteBeginExecuteEvent();
-                TaskCompletionSource<object> completion = new TaskCompletionSource<object>(stateObject);
-
-                ValidateAsyncCommand(); // Special case - done outside of try/catches to prevent putting a stateObj
-                                        // back into pool when we should not.
+                if (!inRetry) {
+                    statistics = SqlStatistics.StartTimer(Statistics);
+                    WriteBeginExecuteEvent();
 
+                    ValidateAsyncCommand(); // Special case - done outside of try/catches to prevent putting a stateObj
+                                            // back into pool when we should not.
+                }
+                
+                bool usedCache;
                 Task writeTask = null;
                 try { // InternalExecuteNonQuery already has reliability block, but if failure will not put stateObj back into pool.
-                    RunExecuteReader(behavior, RunBehavior.ReturnImmediately, true, ADP.BeginExecuteReader, completion, timeout, out writeTask, asyncWrite);
+                    RunExecuteReader(behavior, RunBehavior.ReturnImmediately, true, ADP.BeginExecuteReader, localCompletion, timeout, out writeTask, out usedCache, asyncWrite, inRetry);
                 }
                 catch (Exception e) {
                     if (!ADP.IsCatchableOrSecurityExceptionType(e)) {
@@ -2053,23 +2160,128 @@ namespace System.Data.SqlClient {
                 }
 
                 if (writeTask != null ) {
-                    AsyncHelper.ContinueTask(writeTask,completion,()=> BeginExecuteReaderInternalReadStage(completion));
+                    AsyncHelper.ContinueTask(writeTask, localCompletion, () => BeginExecuteReaderInternalReadStage(localCompletion));
                 }
                 else {
-                    BeginExecuteReaderInternalReadStage(completion);
+                    BeginExecuteReaderInternalReadStage(localCompletion);
+                }
+
+                // When we use query caching for parameter encryption we need to retry on specific errors.
+                // In these cases finalize the call internally and trigger a retry when needed.
+                if (!TriggerInternalEndAndRetryIfNecessary(behavior, stateObject, timeout, ADP.EndExecuteReader, usedCache, inRetry, asyncWrite, globalCompletion, localCompletion, InternalEndExecuteReader, BeginExecuteReaderInternal)) {
+                    globalCompletion = localCompletion;
                 }
 
                 // Add callback after work is done to avoid overlapping Begin\End methods
                 if (callback != null) {
-                    completion.Task.ContinueWith((t) => callback(t), TaskScheduler.Default);
+                    globalCompletion.Task.ContinueWith((t) => callback(t), TaskScheduler.Default);
                 }
-                return completion.Task;
+
+                return globalCompletion.Task;
             }
             finally {
                 SqlStatistics.StopTimer(statistics);
             }
         }
 
+        private bool TriggerInternalEndAndRetryIfNecessary(CommandBehavior behavior, object stateObject, int timeout, string endMethod, bool usedCache, bool inRetry, bool asyncWrite, TaskCompletionSource<object> globalCompletion, TaskCompletionSource<object> localCompletion, Func<IAsyncResult, string, bool, object> endFunc, Func<CommandBehavior, AsyncCallback, object, int, bool, bool, IAsyncResult> retryFunc) {
+            // We shouldn't be using the cache if we are in retry.
+            Debug.Assert(!usedCache || !inRetry);
+
+            // If column ecnryption is enabled and we used the cache, we want to catch any potential exceptions that were caused by the query cache and retry if the error indicates that we should.
+            // So, try to read the result of the query before completing the overall task and trigger a retry if appropriate.
+            if ((IsColumnEncryptionEnabled && !inRetry && usedCache) 
+#if DEBUG
+                || _forceInternalEndQuery
+#endif
+                ) {
+                long firstAttemptStart = ADP.TimerCurrent();
+
+                localCompletion.Task.ContinueWith(tsk => {
+                    if (tsk.IsFaulted) {
+                        globalCompletion.TrySetException(tsk.Exception.InnerException);
+                    }
+                    else if (tsk.IsCanceled) {
+                        globalCompletion.TrySetCanceled();
+                    }
+                    else {
+                        try {
+                            // Mark that we initiated the internal EndExecute. This should always be false until we set it here.
+                            Debug.Assert(!_internalEndExecuteInitiated);
+                            _internalEndExecuteInitiated = true;
+
+                            // lock on _stateObj prevents ----s with close/cancel.
+                            lock (_stateObj) {
+                                endFunc(tsk, endMethod, true/*inInternal*/);
+                            }
+                            globalCompletion.TrySetResult(tsk.Result);
+                        }
+                        catch (Exception e) {
+                            // Put the state object back to the cache.
+                            // Do not reset the async state, since this is managed by the user Begin/End and not internally.
+                            if (ADP.IsCatchableExceptionType(e)) {
+                                ReliablePutStateObject();
+                            }
+
+                            bool shouldRetry = false;
+
+                            // Check if we have an error indicating that we can retry.
+                            if (e is SqlException) {
+                                SqlException sqlEx = e as SqlException;
+
+                                for (int i = 0; i < sqlEx.Errors.Count; i++) {
+                                    if (sqlEx.Errors[i].Number == TdsEnums.TCE_CONVERSION_ERROR_CLIENT_RETRY) {
+                                        shouldRetry = true;
+                                        break;
+                                    }
+                                }
+                            }
+
+                            if (!shouldRetry) {
+                                // If we cannot retry, Reset the async state to make sure we leave a clean state.
+                                if (null != _cachedAsyncState) {
+                                    _cachedAsyncState.ResetAsyncState();
+                                }
+                                _activeConnection.GetOpenTdsConnection().DecrementAsyncCount();
+
+                                globalCompletion.TrySetException(e);
+                            }
+                            else {
+                                // Remove the enrty from the cache since it was inconsistent.
+                                SqlQueryMetadataCache.GetInstance().InvalidateCacheEntry(this);
+
+                                try {
+                                    // Kick off the retry.
+                                    _internalEndExecuteInitiated = false;
+                                    Task<object> retryTask = (Task<object>)retryFunc(behavior, null, stateObject, TdsParserStaticMethods.GetRemainingTimeout(timeout, firstAttemptStart), true/*inRetry*/, asyncWrite);
+
+                                    retryTask.ContinueWith(retryTsk => {
+                                        if (retryTsk.IsFaulted) {
+                                            globalCompletion.TrySetException(retryTsk.Exception.InnerException);
+                                        }
+                                        else if (retryTsk.IsCanceled) {
+                                            globalCompletion.TrySetCanceled();
+                                        }
+                                        else {
+                                            globalCompletion.TrySetResult(retryTsk.Result);
+                                        }
+                                    }, TaskScheduler.Default);
+                                }
+                                catch (Exception e2) {
+                                    globalCompletion.TrySetException(e2);
+                                }
+                            }
+                        }
+                    }
+                }, TaskScheduler.Default);
+
+                return true;
+            }
+            else {
+                return false;
+            }
+        }
+
         private void BeginExecuteReaderInternalReadStage(TaskCompletionSource<object> completion) {
             Debug.Assert(completion != null,"CompletionSource should not be null");
             // Read SNI does not have catches for async exceptions, handle here.
@@ -2123,26 +2335,15 @@ namespace System.Data.SqlClient {
             }
         }
 
-        private SqlDataReader InternalEndExecuteReader(IAsyncResult asyncResult, string endMethod) {
-
-            VerifyEndExecuteState((Task) asyncResult, endMethod);
-            WaitForAsyncResults(asyncResult);
+        private SqlDataReader InternalEndExecuteReader(IAsyncResult asyncResult, string endMethod, bool isInternal) {
+            
+            VerifyEndExecuteState((Task)asyncResult, endMethod);
+            WaitForAsyncResults(asyncResult, isInternal);
 
-            // If Transparent parameter encryption was attempted, then we would have skipped the below 
-            // checks in VerifyEndExecuteState since we wanted to wait for WaitForAsyncResults to complete.
+            // If column encryption is enabled, also check the state after waiting for the task.
+            // It would be better to do this for all cases, but avoiding for compatibility reasons.
             if (IsColumnEncryptionEnabled) {
-                if (cachedAsyncState.EndMethodName == null) {
-                    throw ADP.MethodCalledTwice(endMethod);
-                }
-
-                if (endMethod != cachedAsyncState.EndMethodName) {
-                    throw ADP.MismatchedAsyncResult(cachedAsyncState.EndMethodName, endMethod);
-                }
-
-                if (!cachedAsyncState.IsActiveConnectionValid(_activeConnection)) {
-                    // If the connection is not 'valid' then it was closed while we were executing
-                    throw ADP.ClosedConnectionError();
-                }
+                VerifyEndExecuteState((Task)asyncResult, endMethod, fullCheckForColumnEncryption: true);
             }
 
             CheckThrowSNIException();
@@ -2160,7 +2361,7 @@ namespace System.Data.SqlClient {
                 {
 #endif //DEBUG
                     bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(_activeConnection);
-                    SqlDataReader reader = CompleteAsyncExecuteReader();
+                    SqlDataReader reader = CompleteAsyncExecuteReader(isInternal);
                     Debug.Assert(null == _stateObj, "non-null state object in InternalEndExecuteReader");
                     return reader;
                 }
@@ -2188,7 +2389,7 @@ namespace System.Data.SqlClient {
         public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken) {
 
             Bid.CorrelationTrace("<sc.SqlCommand.ExecuteNonQueryAsync|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
-            SqlConnection.ExecutePermission.Demand();   
+            SqlConnection.ExecutePermission.Demand();
 
             TaskCompletionSource<int> source = new TaskCompletionSource<int>();
 
@@ -2220,7 +2421,7 @@ namespace System.Data.SqlClient {
                         }
                     }
                 }, TaskScheduler.Default);
-            } 
+            }
             catch (Exception e) {
                 source.SetException(e);
             }
@@ -2252,7 +2453,7 @@ namespace System.Data.SqlClient {
         new public Task<SqlDataReader> ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) {
 
             Bid.CorrelationTrace("<sc.SqlCommand.ExecuteReaderAsync|API|Correlation> ObjectID%d#, behavior=%d{ds.CommandBehavior}, ActivityID %ls\n", ObjectID, (int)behavior);
-            SqlConnection.ExecutePermission.Demand();   
+            SqlConnection.ExecutePermission.Demand();
 
             TaskCompletionSource<SqlDataReader> source = new TaskCompletionSource<SqlDataReader>();
 
@@ -2264,12 +2465,12 @@ namespace System.Data.SqlClient {
                 }
                 registration = cancellationToken.Register(CancelIgnoreFailure);
             }
-            
+
             Task<SqlDataReader> returnedTask = source.Task;
             try {
                 RegisterForConnectionCloseNotification(ref returnedTask);
 
-                Task<SqlDataReader>.Factory.FromAsync(BeginExecuteReaderAsync, EndExecuteReaderAsync, behavior, null).ContinueWith((t) => {                    
+                Task<SqlDataReader>.Factory.FromAsync(BeginExecuteReaderAsync, EndExecuteReaderAsync, behavior, null).ContinueWith((t) => {
                     registration.Dispose();
                     if (t.IsFaulted) {
                         Exception e = t.Exception.InnerException;
@@ -2284,7 +2485,7 @@ namespace System.Data.SqlClient {
                         }
                     }
                 }, TaskScheduler.Default);
-            } 
+            }
             catch (Exception e) {
                 source.SetException(e);
             }
@@ -2356,8 +2557,8 @@ namespace System.Data.SqlClient {
         public Task<XmlReader> ExecuteXmlReaderAsync(CancellationToken cancellationToken) {
 
             Bid.CorrelationTrace("<sc.SqlCommand.ExecuteXmlReaderAsync|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
-            SqlConnection.ExecutePermission.Demand();   
-            
+            SqlConnection.ExecutePermission.Demand();
+
             TaskCompletionSource<XmlReader> source = new TaskCompletionSource<XmlReader>();
 
             CancellationTokenRegistration registration = new CancellationTokenRegistration();
@@ -2368,7 +2569,7 @@ namespace System.Data.SqlClient {
                 }
                 registration = cancellationToken.Register(CancelIgnoreFailure);
             }
-            
+
             Task<XmlReader> returnedTask = source.Task;
             try {
                 RegisterForConnectionCloseNotification(ref returnedTask);
@@ -2388,7 +2589,7 @@ namespace System.Data.SqlClient {
                         }
                     }
                 }, TaskScheduler.Default);
-            } 
+            }
             catch (Exception e) {
                 source.SetException(e);
             }
@@ -2882,6 +3083,9 @@ namespace System.Data.SqlClient {
 
                 GetStateObject();
 
+                // Reset the encryption state in case it has been set by a previous command.
+                ResetEncryptionState();
+
                 // we just send over the raw text with no annotation
                 // no parameters are sent over
                 // no data reader is returned
@@ -2993,6 +3197,12 @@ namespace System.Data.SqlClient {
             // First reset the command level state.
             ClearDescribeParameterEncryptionRequests();
 
+            // Reset the state for internal End execution.
+            _internalEndExecuteInitiated = false;
+
+            // Reset the state for the cache.
+            CachingQueryMetadataPostponed = false;
+
             // Reset the state of each of the parameters.
             if (_parameters != null) {
                 for (int i = 0; i < _parameters.Count; i++) {
@@ -3047,13 +3257,13 @@ namespace System.Data.SqlClient {
         /// <param name="task"></param>
         /// <param name="asyncWrite"></param>
         /// <returns></returns>
-        private void PrepareForTransparentEncryption(CommandBehavior cmdBehavior, bool returnStream, bool async, int timeout, TaskCompletionSource<object> completion, out Task returnTask, bool asyncWrite)
-        {
+        private void PrepareForTransparentEncryption(CommandBehavior cmdBehavior, bool returnStream, bool async, int timeout, TaskCompletionSource<object> completion, out Task returnTask, bool asyncWrite, out bool usedCache, bool inRetry) {
             // Fetch reader with input params
             Task fetchInputParameterEncryptionInfoTask = null;
             bool describeParameterEncryptionNeeded = false;
             SqlDataReader describeParameterEncryptionDataReader = null;
             returnTask = null;
+            usedCache = false;
 
             Debug.Assert(_activeConnection != null, "_activeConnection should not be null in PrepareForTransparentEncryption.");
             Debug.Assert(_activeConnection.Parser != null, "_activeConnection.Parser should not be null in PrepareForTransparentEncryption.");
@@ -3064,11 +3274,18 @@ namespace System.Data.SqlClient {
                         "ColumnEncryption setting should be enabled for input parameter encryption.");
             Debug.Assert(async == (completion != null), "completion should can be null if and only if mode is async.");
 
+            // If we are not in Batch RPC and not already retrying, attempt to fetch the cipher MD for each parameter from the cache.
+            // If this succeeds then return immediately, otherwise just fall back to the full crypto MD discovery.
+            if (!BatchRPCMode && !inRetry && SqlQueryMetadataCache.GetInstance().GetQueryMetadataIfExists(this)) {
+                usedCache = true;
+                return;
+            }
+
             // A flag to indicate if finallyblock needs to execute.
             bool processFinallyBlock = true;
 
             // A flag to indicate if we need to decrement async count on the connection in finally block.
-            bool decrementAsyncCountInFinallyBlock = async;
+            bool decrementAsyncCountInFinallyBlock = false;
 
             // Flag to indicate if exception is caught during the execution, to govern clean up.
             bool exceptionCaught = false;
@@ -3118,6 +3335,9 @@ namespace System.Data.SqlClient {
                             return;
                         }
 
+                        // If we are in async execution, we need to decrement our async count on exception.
+                        decrementAsyncCountInFinallyBlock = async;
+
                         Debug.Assert(describeParameterEncryptionDataReader != null,
                             "describeParameterEncryptionDataReader should not be null, as it is required to get results of describe parameter encryption.");
 
@@ -3128,6 +3348,7 @@ namespace System.Data.SqlClient {
                             processFinallyBlock = false;
                             returnTask = AsyncHelper.CreateContinuationTask(fetchInputParameterEncryptionInfoTask, () => {
                                 bool processFinallyBlockAsync = true;
+                                bool decrementAsyncCountInFinallyBlockAsync = true;
 
                                 RuntimeHelpers.PrepareConstrainedRegions();
                                 try {
@@ -3143,14 +3364,13 @@ namespace System.Data.SqlClient {
                                         // If it is async, then TryFetchInputParameterEncryptionInfo-> RunExecuteReaderTds would have incremented the async count.
                                         // Decrement it when we are about to complete async execute reader.
                                         SqlInternalConnectionTds internalConnectionTds = _activeConnection.GetOpenTdsConnection();
-                                        if (internalConnectionTds != null)
-                                        {
+                                        if (internalConnectionTds != null) {
                                             internalConnectionTds.DecrementAsyncCount();
-                                            decrementAsyncCountInFinallyBlock = false;
+                                            decrementAsyncCountInFinallyBlockAsync = false;
                                         }
 
                                         // Complete executereader.
-                                        describeParameterEncryptionDataReader = CompleteAsyncExecuteReader();
+                                        describeParameterEncryptionDataReader = CompleteAsyncExecuteReader(forDescribeParameterEncryption: true);
                                         Debug.Assert(null == _stateObj, "non-null state object in PrepareForTransparentEncryption.");
 
                                         // Read the results of describe parameter encryption.
@@ -3173,7 +3393,7 @@ namespace System.Data.SqlClient {
                                 }
                                 finally {
                                     PrepareTransparentEncryptionFinallyBlock(   closeDataReader: processFinallyBlockAsync,
-                                                                                decrementAsyncCount: decrementAsyncCountInFinallyBlock,
+                                                                                decrementAsyncCount: decrementAsyncCountInFinallyBlockAsync,
                                                                                 clearDataStructures: processFinallyBlockAsync,
                                                                                 wasDescribeParameterEncryptionNeeded: describeParameterEncryptionNeeded,
                                                                                 describeParameterEncryptionRpcOriginalRpcMap: describeParameterEncryptionRpcOriginalRpcMap,
@@ -3187,6 +3407,8 @@ namespace System.Data.SqlClient {
                             if (exception != null) {
                                 throw exception;
                             }}));
+
+                            decrementAsyncCountInFinallyBlock = false;
                         }
                         else {
                             // If it was async, ending the reader is still pending.
@@ -3196,6 +3418,7 @@ namespace System.Data.SqlClient {
                                 processFinallyBlock = false;
                                 returnTask = Task.Run(() => {
                                         bool processFinallyBlockAsync = true;
+                                        bool decrementAsyncCountInFinallyBlockAsync = true;
 
                                         RuntimeHelpers.PrepareConstrainedRegions();
                                         try {
@@ -3214,11 +3437,11 @@ namespace System.Data.SqlClient {
                                                 SqlInternalConnectionTds internalConnectionTds = _activeConnection.GetOpenTdsConnection();
                                                 if (internalConnectionTds != null) {
                                                     internalConnectionTds.DecrementAsyncCount();
-                                                    decrementAsyncCountInFinallyBlock = false;
+                                                    decrementAsyncCountInFinallyBlockAsync = false;
                                                 }
 
                                                 // Complete executereader.
-                                                describeParameterEncryptionDataReader = CompleteAsyncExecuteReader();
+                                                describeParameterEncryptionDataReader = CompleteAsyncExecuteReader(forDescribeParameterEncryption: true);
                                                 Debug.Assert(null == _stateObj, "non-null state object in PrepareForTransparentEncryption.");
 
                                                 // Read the results of describe parameter encryption.
@@ -3242,13 +3465,15 @@ namespace System.Data.SqlClient {
                                         }
                                         finally {
                                             PrepareTransparentEncryptionFinallyBlock(   closeDataReader: processFinallyBlockAsync,
-                                                                                        decrementAsyncCount: decrementAsyncCountInFinallyBlock,
+                                                                                        decrementAsyncCount: decrementAsyncCountInFinallyBlockAsync,
                                                                                         clearDataStructures: processFinallyBlockAsync,
                                                                                         wasDescribeParameterEncryptionNeeded: describeParameterEncryptionNeeded,
                                                                                         describeParameterEncryptionRpcOriginalRpcMap: describeParameterEncryptionRpcOriginalRpcMap,
                                                                                         describeParameterEncryptionDataReader: describeParameterEncryptionDataReader);
                                         }
                                     });
+
+                                decrementAsyncCountInFinallyBlock = false;
                             }
                             else {
                                 // For synchronous execution, read the results of describe parameter encryption here.
@@ -3413,6 +3638,7 @@ namespace System.Data.SqlClient {
                                             timeout: timeout,
                                             task: out task,
                                             asyncWrite: asyncWrite,
+                                            inRetry: false,
                                             ds: null,
                                             describeParameterEncryptionRequest: true);
             }
@@ -3494,6 +3720,13 @@ namespace System.Data.SqlClient {
                     SqlParameter param = originalRpcRequest.parameters[i];
                     paramCopy = new SqlParameter(param.ParameterName, param.SqlDbType, param.Size, param.Direction, param.Precision, param.Scale, param.SourceColumn, param.SourceVersion,
                         param.SourceColumnNullMapping, param.Value, param.XmlSchemaCollectionDatabase, param.XmlSchemaCollectionOwningSchema, param.XmlSchemaCollectionName);
+                    paramCopy.CompareInfo = param.CompareInfo;
+                    paramCopy.TypeName = param.TypeName;
+                    paramCopy.UdtTypeName = param.UdtTypeName;
+                    paramCopy.IsNullable = param.IsNullable;
+                    paramCopy.LocaleId = param.LocaleId;
+                    paramCopy.Offset = param.Offset;
+
                     tempCollection.Add(paramCopy);
                 }
 
@@ -3715,18 +3948,25 @@ namespace System.Data.SqlClient {
                     }
                 }
             }
+
+            // If we are not in Batch RPC mode, update the query cache with the encryption MD.
+            if (!BatchRPCMode) {
+                SqlQueryMetadataCache.GetInstance().AddQueryMetadata(this, ignoreQueriesWithReturnValueParams: true);
+            }
         }
 
         internal SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, string method) {
             Task unused; // sync execution 
-            SqlDataReader reader = RunExecuteReader(cmdBehavior, runBehavior, returnStream, method, completion:null, timeout:CommandTimeout, task:out unused);
+            bool usedCache;
+            SqlDataReader reader = RunExecuteReader(cmdBehavior, runBehavior, returnStream, method, completion: null, timeout: CommandTimeout, task: out unused, usedCache: out usedCache);
             Debug.Assert(unused == null, "returned task during synchronous execution");
             return reader;
         }
 
         // task is created in case of pending asynchronous write, returned SqlDataReader should not be utilized until that task is complete 
-        internal SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, string method, TaskCompletionSource<object> completion, int timeout, out Task task, bool asyncWrite = false) {
+        internal SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, string method, TaskCompletionSource<object> completion, int timeout, out Task task, out bool usedCache, bool asyncWrite = false, bool inRetry = false) {
             bool async = (null != completion);
+            usedCache = false;
 
             task = null;
 
@@ -3740,7 +3980,10 @@ namespace System.Data.SqlClient {
 
             // @devnote: this function may throw for an invalid connection
             // @devnote: returns false for empty command text
-            ValidateCommand(method, async);
+            if (!inRetry) {
+                ValidateCommand(method, async);
+            }
+
             CheckNotificationStateAndAutoEnlist(); // Only call after validate - requires non null connection!
 
             TdsParser bestEffortCleanupTarget = null;
@@ -3777,14 +4020,46 @@ namespace System.Data.SqlClient {
                     }
                     else if (IsColumnEncryptionEnabled) {
                         Task returnTask = null;
-                        PrepareForTransparentEncryption(cmdBehavior, returnStream, async, timeout, completion, out returnTask, asyncWrite && async);
-                        Debug.Assert(async == (returnTask != null), @"returnTask should be null if and only if async is false.");
+                        PrepareForTransparentEncryption(cmdBehavior, returnStream, async, timeout, completion, out returnTask, asyncWrite && async, out usedCache, inRetry);
+                        Debug.Assert(usedCache || (async == (returnTask != null)), @"if we didn't use the cache, returnTask should be null if and only if async is false.");
+
+                        long firstAttemptStart = ADP.TimerCurrent();
 
-                        return RunExecuteReaderTdsWithTransparentParameterEncryption( cmdBehavior, runBehavior, returnStream, async, timeout, out task, asyncWrite && async, ds: null,
-                            describeParameterEncryptionRequest: false, describeParameterEncryptionTask: returnTask);
+                        try {
+                            return RunExecuteReaderTdsWithTransparentParameterEncryption(cmdBehavior, runBehavior, returnStream, async, timeout, out task, asyncWrite && async, inRetry: inRetry, ds: null,
+                                describeParameterEncryptionRequest: false, describeParameterEncryptionTask: returnTask);
+                        }
+                        catch (SqlException ex) {
+                            // We only want to retry once, so don't retry if we are already in retry.
+                            // If we didn't use the cache, we don't want to retry.
+                            // The async retried are handled separately, handle only [....] calls here.
+                            if (inRetry || async || !usedCache) {
+                                throw;
+                            }
+
+                            bool shouldRetry = false;
+
+                            // Check if we have an error indicating that we can retry.
+                            for (int i = 0; i < ex.Errors.Count; i++) {
+                                if (ex.Errors[i].Number == TdsEnums.TCE_CONVERSION_ERROR_CLIENT_RETRY) {
+                                    shouldRetry = true;
+                                    break;
+                                }
+                            }
+
+                            if (!shouldRetry) {
+                                throw;
+                            }
+                            else {
+                                // Retry if the command failed with appropriate error.
+                                // First invalidate the entry from the cache, so that we refresh our encryption MD.
+                                SqlQueryMetadataCache.GetInstance().InvalidateCacheEntry(this);
+                                return RunExecuteReader(cmdBehavior, runBehavior, returnStream, method, null, TdsParserStaticMethods.GetRemainingTimeout(timeout, firstAttemptStart), out task, out usedCache, async, inRetry: true);
+                            }
+                        }
                     }
                     else {
-                        return RunExecuteReaderTds( cmdBehavior, runBehavior, returnStream, async, timeout, out task, asyncWrite && async);
+                        return RunExecuteReaderTds( cmdBehavior, runBehavior, returnStream, async, timeout, out task, asyncWrite && async, inRetry: inRetry);
                     }
 
                 }
@@ -3830,11 +4105,11 @@ namespace System.Data.SqlClient {
                                                                                     int timeout,
                                                                                     out Task task,
                                                                                     bool asyncWrite,
+                                                                                    bool inRetry,
                                                                                     SqlDataReader ds=null,
                                                                                     bool describeParameterEncryptionRequest = false,
                                                                                     Task describeParameterEncryptionTask = null) {
             Debug.Assert(!asyncWrite || async, "AsyncWrite should be always accompanied by Async");
-            Debug.Assert((describeParameterEncryptionTask != null) == async, @"async should be true if and only if describeParameterEncryptionTask is not null.");
 
             if (ds == null && returnStream) {
                 ds = new SqlDataReader(this, cmdBehavior);
@@ -3842,40 +4117,42 @@ namespace System.Data.SqlClient {
 
             if (describeParameterEncryptionTask != null) {
                 long parameterEncryptionStart = ADP.TimerCurrent();
-                    TaskCompletionSource<object> completion = new TaskCompletionSource<object>();
-                    AsyncHelper.ContinueTask(describeParameterEncryptionTask, completion,
-                        () => {
-                            Task subTask = null;
-                            RunExecuteReaderTds(cmdBehavior, runBehavior, returnStream, async, TdsParserStaticMethods.GetRemainingTimeout(timeout, parameterEncryptionStart), out subTask, asyncWrite, ds);
-                            if (subTask == null) {
-                                completion.SetResult(null);
-                            }
-                            else {
-                                AsyncHelper.ContinueTask(subTask, completion, () => completion.SetResult(null));
-                            }
-                        }, connectionToDoom: null,
-                        onFailure: ((exception) => {
-                            if (_cachedAsyncState != null) {
-                                _cachedAsyncState.ResetAsyncState();
-                            }
-                            if (exception != null) {
-                                throw exception;
-                            }}),
-                        onCancellation: (() => {
-                            if (_cachedAsyncState != null) {
-                                _cachedAsyncState.ResetAsyncState();
-                            }}),
-                        connectionToAbort: _activeConnection);
-                    task = completion.Task;
-                    return ds;
+                TaskCompletionSource<object> completion = new TaskCompletionSource<object>();
+                AsyncHelper.ContinueTask(describeParameterEncryptionTask, completion,
+                    () => {
+                        Task subTask = null;
+                        RunExecuteReaderTds(cmdBehavior, runBehavior, returnStream, async, TdsParserStaticMethods.GetRemainingTimeout(timeout, parameterEncryptionStart), out subTask, asyncWrite, inRetry, ds);
+                        if (subTask == null) {
+                            completion.SetResult(null);
+                        }
+                        else {
+                            AsyncHelper.ContinueTask(subTask, completion, () => completion.SetResult(null));
+                        }
+                    }, connectionToDoom: null,
+                    onFailure: ((exception) => {
+                        if (_cachedAsyncState != null) {
+                            _cachedAsyncState.ResetAsyncState();
+                        }
+                        if (exception != null) {
+                            throw exception;
+                        }
+                    }),
+                    onCancellation: (() => {
+                        if (_cachedAsyncState != null) {
+                            _cachedAsyncState.ResetAsyncState();
+                        }
+                    }),
+                    connectionToAbort: _activeConnection);
+                task = completion.Task;
+                return ds;
             }
             else {
                 // Synchronous execution.
-                return RunExecuteReaderTds(cmdBehavior, runBehavior, returnStream, async, timeout, out task, asyncWrite, ds);
+                return RunExecuteReaderTds(cmdBehavior, runBehavior, returnStream, async, timeout, out task, asyncWrite, inRetry, ds);
             }
         }
 
-        private SqlDataReader RunExecuteReaderTds( CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, bool async, int timeout, out Task task, bool asyncWrite, SqlDataReader ds=null, bool describeParameterEncryptionRequest = false) {
+        private SqlDataReader RunExecuteReaderTds( CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, bool async, int timeout, out Task task, bool asyncWrite, bool inRetry, SqlDataReader ds=null, bool describeParameterEncryptionRequest = false) {
             Debug.Assert(!asyncWrite || async, "AsyncWrite should be always accompanied by Async");
 
             if (ds == null && returnStream) {
@@ -3900,7 +4177,7 @@ namespace System.Data.SqlClient {
                             Interlocked.CompareExchange(ref _reconnectionCompletionSource, null, completion);
                             timeoutCTS.Cancel();
                             Task subTask;                            
-                            RunExecuteReaderTds(cmdBehavior, runBehavior, returnStream, async, TdsParserStaticMethods.GetRemainingTimeout(timeout, reconnectionStart), out subTask, asyncWrite, ds);
+                            RunExecuteReaderTds(cmdBehavior, runBehavior, returnStream, async, TdsParserStaticMethods.GetRemainingTimeout(timeout, reconnectionStart), out subTask, asyncWrite, inRetry, ds);
                             if (subTask == null) {
                                 completion.SetResult(null);
                             }
@@ -3933,7 +4210,8 @@ namespace System.Data.SqlClient {
             bool processFinallyBlock = true;
             bool decrementAsyncCountOnFailure = false;
 
-            if (async) {
+            // If we are in retry, don't increment the Async count. This should have already been set.
+            if (async && !inRetry) {
                 _activeConnection.GetOpenTdsConnection().IncrementAsyncCount();
                 decrementAsyncCountOnFailure = true;
             }
@@ -4077,7 +4355,7 @@ namespace System.Data.SqlClient {
                 }
                 else {
                     // Always execute - even if no reader!
-                    FinishExecuteReader(ds, runBehavior, optionSettings);
+                    FinishExecuteReader(ds, runBehavior, optionSettings, isInternal: false, forDescribeParameterEncryption: false);
                 }
             }
             catch (Exception e) {                
@@ -4177,11 +4455,11 @@ namespace System.Data.SqlClient {
         return ds;
         }
 
-        private SqlDataReader CompleteAsyncExecuteReader() {
+        private SqlDataReader CompleteAsyncExecuteReader(bool isInternal = false, bool forDescribeParameterEncryption = false) {
             SqlDataReader ds = cachedAsyncState.CachedAsyncReader; // should not be null
             bool processFinallyBlock = true;
             try {
-                FinishExecuteReader(ds, cachedAsyncState.CachedRunBehavior, cachedAsyncState.CachedSetOptions);
+                FinishExecuteReader(ds, cachedAsyncState.CachedRunBehavior, cachedAsyncState.CachedSetOptions, isInternal, forDescribeParameterEncryption);
             }
             catch (Exception e) {
                 processFinallyBlock = ADP.IsCatchableExceptionType(e);
@@ -4190,7 +4468,11 @@ namespace System.Data.SqlClient {
             finally {
                 TdsParser.ReliabilitySection.Assert("unreliable call to CompleteAsyncExecuteReader");  // you need to setup for a thread abort somewhere before you call this method
                 if (processFinallyBlock) {
-                    cachedAsyncState.ResetAsyncState();
+                    // Don't reset the state for internal End. The user End will do that eventually.
+                    if (!isInternal) {
+                        cachedAsyncState.ResetAsyncState();
+                    }
+
                     PutStateObject();
                 }
             }
@@ -4198,10 +4480,19 @@ namespace System.Data.SqlClient {
             return ds;
         }
 
-        private void FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, string resetOptionsString) {
+        private void FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, string resetOptionsString, bool isInternal, bool forDescribeParameterEncryption) {
             // always wrap with a try { FinishExecuteReader(...) } finally { PutStateObject(); }
 
-            NotifyDependency();
+            // If this is not for internal usage, notify the dependency. If we have already initiated the end internally, the reader should be ready, so just return.
+            if (!isInternal && !forDescribeParameterEncryption) {
+                NotifyDependency();
+
+                if (_internalEndExecuteInitiated) {
+                    Debug.Assert(_stateObj == null);
+                    return;
+                }
+            }
+
             if (runBehavior == RunBehavior.UntilDone) {
                 try {
                     bool dataReady;
@@ -4618,6 +4909,14 @@ namespace System.Data.SqlClient {
                         parameter.Value = status;
 
                     }
+
+                // If we are not in Batch RPC mode, update the query cache with the encryption MD.
+                // We can do this now that we have distinguished between ReturnValue and ReturnStatus.
+                // Read comment in AddQueryMetadata() for more details.
+                if (!BatchRPCMode && CachingQueryMetadataPostponed) {
+                    SqlQueryMetadataCache.GetInstance().AddQueryMetadata(this, ignoreQueriesWithReturnValueParams: false);
+                }
+
                     break;
                 }
             }
index 0ce4dbb08763054308721ed6139b428134b0cb54..306a42079800e4f74776c8f8f967a9df88f0c8f5 100644 (file)
@@ -88,7 +88,51 @@ namespace System.Data.SqlClient
                 return _ColumnEncryptionTrustedMasterKeyPaths;
             }
         }
-        
+
+        /// <summary>
+        /// Defines whether query metadata caching is enabled.
+        /// </summary>
+        static private bool _ColumnEncryptionQueryMetadataCacheEnabled = true;
+
+        [
+        DefaultValue(null),
+        ResCategoryAttribute(Res.DataCategory_Data),
+        ResDescriptionAttribute(Res.TCE_SqlConnection_ColumnEncryptionQueryMetadataCacheEnabled),
+        ]
+        static public bool ColumnEncryptionQueryMetadataCacheEnabled 
+        {
+            get
+            {
+                return _ColumnEncryptionQueryMetadataCacheEnabled;
+            }
+            set
+            {
+                _ColumnEncryptionQueryMetadataCacheEnabled = value;
+            }
+        }
+
+        /// <summary>
+        /// Defines whether query metadata caching is enabled.
+        /// </summary>
+        static private TimeSpan _ColumnEncryptionKeyCacheTtl = TimeSpan.FromHours(2);
+
+        [
+        DefaultValue(null),
+        ResCategoryAttribute(Res.DataCategory_Data),
+        ResDescriptionAttribute(Res.TCE_SqlConnection_ColumnEncryptionKeyCacheTtl),
+        ]
+        static public TimeSpan ColumnEncryptionKeyCacheTtl
+        {
+            get
+            {
+                return _ColumnEncryptionKeyCacheTtl;
+            }
+            set
+            {
+                _ColumnEncryptionKeyCacheTtl = value;
+            }
+        }
+
         /// <summary>
         /// This function should only be called once in an app. This does shallow copying of the dictionary so that 
         /// the app cannot alter the custom provider list once it has been set.
@@ -437,7 +481,15 @@ namespace System.Data.SqlClient
             get {
                 return ((SqlConnectionString)ConnectionOptions).TypeSystemAssemblyVersion;
             }
-        }        
+        }     
+        
+        internal PoolBlockingPeriod PoolBlockingPeriod
+        {
+            get
+            {
+                return ((SqlConnectionString)ConnectionOptions).PoolBlockingPeriod;
+            }
+        }   
 
         internal int ConnectRetryInterval {
             get {
index 85ed1b7bbf0f70519c0eb866a1584df11633861a..1dd74aec96b5bb8d171dad19d2f1fdad331e7ced 100644 (file)
@@ -30,6 +30,7 @@ namespace System.Data.SqlClient {
             internal const  string Application_Name               = TdsEnums.SQL_PROVIDER_NAME;
             internal const  bool   Asynchronous                   = false;
             internal const  string AttachDBFilename               = "";
+            internal const  PoolBlockingPeriod PoolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod;
             internal const  int    Connect_Timeout                = ADP.DefaultConnectionTimeout;
             internal const  bool   Connection_Reset               = true;
             internal const  bool   Context_Connection             = false;
@@ -69,6 +70,7 @@ namespace System.Data.SqlClient {
             internal const string Application_Name                                     = "application name";
             internal const string AsynchronousProcessing                       = "asynchronous processing";
             internal const string AttachDBFilename                                     = "attachdbfilename";
+            internal const string PoolBlockingPeriod                = "poolblockingperiod";
             internal const string ColumnEncryptionSetting                      = "column encryption setting";
             internal const string Connect_Timeout                                      = "connect timeout";
             internal const string Connection_Reset                                     = "connection reset";
@@ -190,6 +192,7 @@ namespace System.Data.SqlClient {
 
         private readonly bool _integratedSecurity;
 
+        private readonly PoolBlockingPeriod _poolBlockingPeriod;
         private readonly bool _connectionReset;
         private readonly bool _contextConnection;
         private readonly bool _encrypt;
@@ -247,6 +250,7 @@ namespace System.Data.SqlClient {
             ConvertValueToBoolean(KEY.AsynchronousProcessing, DEFAULT.Asynchronous); // while we don't use it anymore, we still need to verify it is true/false
 
             // SQLPT 41700: Ignore ResetConnection=False (still validate the keyword/value)
+            _poolBlockingPeriod = ConvertValueToPoolBlockingPeriod();
             _connectionReset     = ConvertValueToBoolean(KEY.Connection_Reset,      DEFAULT.Connection_Reset);
             _contextConnection   = ConvertValueToBoolean(KEY.Context_Connection,    DEFAULT.Context_Connection);
             _encrypt             = ConvertValueToEncrypt();
@@ -490,6 +494,7 @@ namespace System.Data.SqlClient {
             _userInstance                   = userInstance;
             _connectTimeout                 = connectionOptions._connectTimeout;
             _loadBalanceTimeout             = connectionOptions._loadBalanceTimeout;
+            _poolBlockingPeriod       = connectionOptions._poolBlockingPeriod;
             _maxPoolSize                    = connectionOptions._maxPoolSize;
             _minPoolSize                    = connectionOptions._minPoolSize;
             _multiSubnetFailover            = connectionOptions._multiSubnetFailover;
@@ -525,6 +530,8 @@ namespace System.Data.SqlClient {
         // will work.  In the future we can deprecate the keyword entirely.
         internal bool Asynchronous { get { return true; } }
 
+        internal PoolBlockingPeriod PoolBlockingPeriod { get { return _poolBlockingPeriod; } }
+
         // SQLPT 41700: Ignore ResetConnection=False, always reset the connection for security
         internal bool ConnectionReset { get { return true; } }
         internal bool ContextConnection { get { return _contextConnection; } }
@@ -620,6 +627,7 @@ namespace System.Data.SqlClient {
                 hash.Add(KEY.Application_Name,               KEY.Application_Name);
                 hash.Add(KEY.AsynchronousProcessing,         KEY.AsynchronousProcessing);
                 hash.Add(KEY.AttachDBFilename,               KEY.AttachDBFilename);
+                hash.Add(KEY.PoolBlockingPeriod,       KEY.PoolBlockingPeriod);
                 hash.Add(KEY.Connect_Timeout,                KEY.Connect_Timeout);
                 hash.Add(KEY.Connection_Reset,               KEY.Connection_Reset);
                 hash.Add(KEY.Context_Connection,             KEY.Context_Connection);
@@ -779,6 +787,28 @@ namespace System.Data.SqlClient {
             // ArgumentException and other types are raised as is (no wrapping)
         }
 
+        internal System.Data.SqlClient.PoolBlockingPeriod ConvertValueToPoolBlockingPeriod()
+        {
+            object value = base.Parsetable[KEY.PoolBlockingPeriod];
+            if (value == null)
+            {
+                return DEFAULT.PoolBlockingPeriod;
+            }
+            
+            try
+            {
+                return DbConnectionStringBuilderUtil.ConvertToPoolBlockingPeriod(KEY.PoolBlockingPeriod, value);
+            }
+            catch (FormatException e)
+            {
+                throw ADP.InvalidConnectionOptionValue(KEY.PoolBlockingPeriod, e);
+            }
+            catch (OverflowException e)
+            {
+                throw ADP.InvalidConnectionOptionValue(KEY.PoolBlockingPeriod, e);
+            }
+        }
+
         internal SqlAuthenticationMethod ConvertValueToAuthenticationType() {
             object value = base.Parsetable[KEY.Authentication];
 
index 8e7714341c4b24753db6afad82f66a0736f39837..ae3c2b1e67e496209866a659317ded681c7bbde8 100644 (file)
@@ -41,6 +41,7 @@ namespace System.Data.SqlClient {
             Pooling,
             MinPoolSize,
             MaxPoolSize,
+            PoolBlockingPeriod,
 
             AsynchronousProcessing,
             ConnectionReset,
@@ -127,6 +128,7 @@ namespace System.Data.SqlClient {
         private bool _userInstance                                     = DbConnectionStringDefaults.UserInstance;
         private SqlAuthenticationMethod _authentication     = DbConnectionStringDefaults.Authentication;
         private SqlConnectionColumnEncryptionSetting _columnEncryptionSetting = DbConnectionStringDefaults.ColumnEncryptionSetting;
+        private PoolBlockingPeriod _poolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod;
 
         static SqlConnectionStringBuilder() {
             string[] validKeywords = new string[KeywordsCount];
@@ -134,6 +136,7 @@ namespace System.Data.SqlClient {
             validKeywords[(int)Keywords.ApplicationName]                = DbConnectionStringKeywords.ApplicationName;
             validKeywords[(int)Keywords.AsynchronousProcessing]         = DbConnectionStringKeywords.AsynchronousProcessing;
             validKeywords[(int)Keywords.AttachDBFilename]               = DbConnectionStringKeywords.AttachDBFilename;
+            validKeywords[(int)Keywords.PoolBlockingPeriod]       = DbConnectionStringKeywords.PoolBlockingPeriod;
             validKeywords[(int)Keywords.ConnectionReset]                = DbConnectionStringKeywords.ConnectionReset;
             validKeywords[(int)Keywords.ContextConnection]              = DbConnectionStringKeywords.ContextConnection;
             validKeywords[(int)Keywords.ConnectTimeout]                 = DbConnectionStringKeywords.ConnectTimeout;
@@ -174,6 +177,7 @@ namespace System.Data.SqlClient {
             hash.Add(DbConnectionStringKeywords.ApplicationName,                                       Keywords.ApplicationName);
             hash.Add(DbConnectionStringKeywords.AsynchronousProcessing,                                Keywords.AsynchronousProcessing);
             hash.Add(DbConnectionStringKeywords.AttachDBFilename,                                      Keywords.AttachDBFilename);
+            hash.Add(DbConnectionStringKeywords.PoolBlockingPeriod,           Keywords.PoolBlockingPeriod);
             hash.Add(DbConnectionStringKeywords.ConnectTimeout,                                                Keywords.ConnectTimeout);
             hash.Add(DbConnectionStringKeywords.ConnectionReset,                                       Keywords.ConnectionReset);
             hash.Add(DbConnectionStringKeywords.ContextConnection,                                     Keywords.ContextConnection);
@@ -278,6 +282,7 @@ namespace System.Data.SqlClient {
                     case Keywords.Authentication:                                      Authentication = ConvertToAuthenticationType(keyword, value); break;
                     case Keywords.ColumnEncryptionSetting:                     ColumnEncryptionSetting = ConvertToColumnEncryptionSetting(keyword, value); break;
                     case Keywords.AsynchronousProcessing:                      AsynchronousProcessing = ConvertToBoolean(value); break;
+                    case Keywords.PoolBlockingPeriod:               PoolBlockingPeriod = ConvertToPoolBlockingPeriod(keyword, value); break;
 #pragma warning disable 618 // Obsolete ConnectionReset
                     case Keywords.ConnectionReset:                                     ConnectionReset = ConvertToBoolean(value); break;
 #pragma warning restore 618
@@ -360,6 +365,25 @@ namespace System.Data.SqlClient {
             }
         }
 
+        [DisplayName(DbConnectionStringKeywords.PoolBlockingPeriod)]
+        [ResCategoryAttribute(Res.DataCategory_Pooling)]
+        [ResDescriptionAttribute(Res.DbConnectionString_PoolBlockingPeriod)]
+        [RefreshPropertiesAttribute(RefreshProperties.All)]
+        public PoolBlockingPeriod PoolBlockingPeriod
+        {
+            get { return _poolBlockingPeriod; }
+            set
+            {
+                if (!DbConnectionStringBuilderUtil.IsValidPoolBlockingPeriodValue(value))
+                {
+                    throw ADP.InvalidEnumerationValue(typeof(PoolBlockingPeriod), (int)value);
+                }
+
+                SetPoolBlockingPeriodValue(value);
+                _poolBlockingPeriod = value;
+            }
+        }
+
         [Browsable(false)]
         [DisplayName(DbConnectionStringKeywords.ConnectionReset)]
         [Obsolete("ConnectionReset has been deprecated.  SqlConnection will ignore the 'connection reset' keyword and always reset the connection")] // SQLPT 41700
@@ -881,6 +905,10 @@ namespace System.Data.SqlClient {
         private static SqlAuthenticationMethod ConvertToAuthenticationType(string keyword, object value) {
             return DbConnectionStringBuilderUtil.ConvertToAuthenticationType(keyword, value);
         }
+        private static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value)
+        {
+            return DbConnectionStringBuilderUtil.ConvertToPoolBlockingPeriod(keyword, value);
+        }
 
         /// <summary>
         /// Convert to SqlConnectionColumnEncryptionSetting.
@@ -906,6 +934,7 @@ namespace System.Data.SqlClient {
             case Keywords.ApplicationName:                                     return ApplicationName;
             case Keywords.AsynchronousProcessing:                      return AsynchronousProcessing;
             case Keywords.AttachDBFilename:                                    return AttachDBFilename;
+            case Keywords.PoolBlockingPeriod:         return PoolBlockingPeriod;
             case Keywords.ConnectTimeout:                                      return ConnectTimeout;
 #pragma warning disable 618 // Obsolete ConnectionReset
             case Keywords.ConnectionReset:                                     return ConnectionReset;
@@ -1012,6 +1041,10 @@ namespace System.Data.SqlClient {
             case Keywords.Authentication:
                 _authentication = DbConnectionStringDefaults.Authentication;
                 break;
+            case Keywords.PoolBlockingPeriod:
+                _poolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod;
+                break;
+              
             case Keywords.ConnectTimeout:
                 _connectTimeout = DbConnectionStringDefaults.ConnectTimeout;
                 break;
@@ -1128,6 +1161,11 @@ namespace System.Data.SqlClient {
             Debug.Assert(DbConnectionStringBuilderUtil.IsValidApplicationIntentValue(value), "Invalid value for ApplicationIntent");
             base[DbConnectionStringKeywords.ApplicationIntent] = DbConnectionStringBuilderUtil.ApplicationIntentToString(value);
         }
+        private void SetPoolBlockingPeriodValue(PoolBlockingPeriod value)
+        {
+            Debug.Assert(DbConnectionStringBuilderUtil.IsValidPoolBlockingPeriodValue(value), "Invalid value for PoolBlockingPeriod");
+            base[DbConnectionStringKeywords.PoolBlockingPeriod] = DbConnectionStringBuilderUtil.PoolBlockingPeriodToString(value);
+        }
         private void SetAuthenticationValue(SqlAuthenticationMethod value) {
             Debug.Assert(DbConnectionStringBuilderUtil.IsValidAuthenticationTypeValue(value), "Invalid value for AuthenticationType");
             base[DbConnectionStringKeywords.Authentication] = DbConnectionStringBuilderUtil.AuthenticationTypeToString(value);
index 879a86d61a86854b73492bcc168c5a36981ddd30..0e799476baf0274495dc018a71786619b463df93 100644 (file)
@@ -207,10 +207,10 @@ namespace System.Data.SqlClient
                     durationString = null;
                     break;
             }
-
+            
             // This message is to be added only when within the various stages of a connection. 
             // In all other cases, it will default to the original error message.
-            if ((currentPhase != SqlConnectionTimeoutErrorPhase.Undefined) || (currentPhase != SqlConnectionTimeoutErrorPhase.Complete))
+            if ((currentPhase != SqlConnectionTimeoutErrorPhase.Undefined) && (currentPhase != SqlConnectionTimeoutErrorPhase.Complete))
             {
                 // NOTE: In case of a failover scenario, add a string that this failure occured as part of the primary or secondary server
                 if (isFailoverScenario)
@@ -229,13 +229,13 @@ namespace System.Data.SqlClient
                         originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration(),
                         originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration());
                 }
+            }
 
-                // NOTE: To display duration in each phase.
-                if (durationString != null)
-                {
-                    errorBuilder.Append("  ");
-                    errorBuilder.Append(durationString);
-                }
+            // NOTE: To display duration in each phase.
+            if (durationString != null)
+            {
+                errorBuilder.Append("  ");
+                errorBuilder.Append(durationString);
             }
 
             return errorBuilder.ToString();
index c07b195ac1ba68e64a6342f0c03bbc6e4bc32456..376909b9abd7bd6b626018dfbe5b83b5a12940c2 100644 (file)
@@ -889,6 +889,7 @@ namespace System.Data.SqlClient
         }
 
         internal void DecrementAsyncCount() {
+            Debug.Assert(_asyncCommandCount > 0);
             Interlocked.Decrement(ref _asyncCommandCount);
         }
 
index 9b238a4706148ac933a6ffd8c093e4fb4f4ad05b..81274a6b846ff9ca223b8feaeb2f3a9422a373dc 100644 (file)
@@ -99,9 +99,6 @@ namespace System.Data.SqlClient {
             }
 
             set {
-                Debug.Assert(_columnEncryptionCipherMetadata == null || value == null,
-                    "_columnEncryptionCipherMetadata should be set to a non-null value only once.");
-
                 _columnEncryptionCipherMetadata = value;
             }
         }
index fa371fb7222e0bd2cdcc10e7741675889e5fb845..8df0617428c5287d40e613faeb2239ca344dcaee 100644 (file)
@@ -13,18 +13,19 @@ namespace System.Data.SqlClient {
     using System.Diagnostics;
     using System.Globalization;
     using System.Linq;
+    using System.Runtime.Caching;
     using System.Text;
 
     /// <summary>
     /// <para> Implements a cache of Symmetric Keys (once they are decrypted).Useful for rapidly decrypting multiple data values.</para>
     /// </summary>
     sealed internal class SqlSymmetricKeyCache {
-        private readonly ConcurrentDictionary<string,SqlClientSymmetricKey> _cache;
+        private readonly MemoryCache _cache;
         private static readonly SqlSymmetricKeyCache _singletonInstance = new SqlSymmetricKeyCache();
 
 
         private SqlSymmetricKeyCache () {
-            _cache = new ConcurrentDictionary<string, SqlClientSymmetricKey>(concurrencyLevel: 4 * Environment.ProcessorCount /* default value in ConcurrentDictionary*/, capacity: 2);
+            _cache = new MemoryCache("ColumnEncryptionKeyCache");
         }
 
         internal static SqlSymmetricKeyCache GetInstance () {
@@ -54,10 +55,10 @@ namespace System.Data.SqlClient {
             Debug.Assert(cacheLookupKey.Length <= capacity, "We needed to allocate a larger array");
 #endif //DEBUG
 
-            encryptionKey = null;
-
             // Lookup the key in cache
-            if (!_cache.TryGetValue(cacheLookupKey, out encryptionKey)) {
+            encryptionKey = _cache.Get(cacheLookupKey) as SqlClientSymmetricKey;
+            
+            if (encryptionKey == null) {
                 Debug.Assert(SqlConnection.ColumnEncryptionTrustedMasterKeyPaths != null, @"SqlConnection.ColumnEncryptionTrustedMasterKeyPaths should not be null");
 
                 // Check against the trusted key paths
@@ -96,9 +97,13 @@ namespace System.Data.SqlClient {
 
                 encryptionKey = new SqlClientSymmetricKey (plaintextKey);
 
-                // In case multiple threads reach here at the same time, the first one wins.
-                // The allocated memory will be reclaimed by Garbage Collector.
-                _cache.TryAdd(cacheLookupKey, encryptionKey);
+                // If the cache TTL is zero, don't even bother inserting to the cache.
+                if (SqlConnection.ColumnEncryptionKeyCacheTtl != TimeSpan.Zero) {
+                    // In case multiple threads reach here at the same time, the first one wins.
+                    // The allocated memory will be reclaimed by Garbage Collector.
+                    DateTimeOffset expirationTime = DateTimeOffset.UtcNow.Add(SqlConnection.ColumnEncryptionKeyCacheTtl);
+                    _cache.Add(cacheLookupKey, encryptionKey, expirationTime);
+                }
             }
 
             return true;
index ae7086f0a0608738e7f68bea83af34dc3b580978..a15b18937676d5a39c673416098253c5b7c40546 100644 (file)
@@ -1543,7 +1543,7 @@ namespace System.Data.SqlClient {
             return Res.GetString(Res.SQL_SSPIGenerateError);
         }
         static internal string Timeout() {
-            return Res.GetString(Res.SQL_Timeout);
+            return Res.GetString(Res.SQL_Timeout_Execution);
         }
         static internal string Timeout_PreLogin_Begin() {
             return Res.GetString(Res.SQL_Timeout_PreLogin_Begin);
index 319e252b21b826ab021665c375d7941afb450591..11e3cdd98efd79562964e1fcaf8bac00e1dd2999 100644 (file)
@@ -544,6 +544,9 @@ namespace System.Data.SqlClient {
         public const int IMPERSONATION_FAILED = 1346;
         public const int P_TOKENTOOLONG = 103;
 
+        // SQL error that indicates retry for Always Encrypted
+        public const int TCE_CONVERSION_ERROR_CLIENT_RETRY = 33514;
+
         // SNI\Win32 error values
         // NOTE: these are simply windows system error codes, not SNI specific
         public const uint  SNI_UNINITIALIZED        = unchecked((uint)-1);
index f8f3d1d95c519a2aff87a3ad758b5af41d56cb60..1af6e149ac5103925822c259ea1348fca50f5cf6 100644 (file)
@@ -883,7 +883,6 @@ namespace System.Xml {
             RealFoliate();
             AssertValid();
             if ( NodeType == XPathNodeType.Namespace ) {
-                Debug.Assert( _parentOfNS != null );
                 MoveTo( _parentOfNS );
                 return true;
             }
index 8a130a0f34285449d7dc69480eff98e832bf3edd..9224bf8b8fbac5bb40399ab2c13c752e3f0fd57f 100644 (file)
@@ -3,6 +3,15 @@
 //   Copyright (c) Microsoft Corporation.  All rights reserved.
 // 
 // ==--==
+
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 using System;
 using System.Collections.Generic;
 
@@ -167,3 +176,5 @@ namespace System
         static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
     }
 }
+
+#pragma warning restore 436
index f05b599ed3d2b9af36cb7cd29c3c39123370cf6e..33662b54280621d4ef98247f98badecf87773fda 100644 (file)
@@ -4,6 +4,14 @@
 // 
 // ==--==
 
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches
 using System;
 using System.Collections.Generic;
@@ -126,3 +134,5 @@ namespace System
         }
     }
 }
+
+#pragma warning restore 436
index 4113bd328c7cbca5fae68c51b09f8a09eb459ea4..7561fffb97fc10cc47b715f422fee4b0ce0a6a15 100644 (file)
@@ -5,12 +5,14 @@
 namespace System.IdentityModel.Claims
 {
     using System.Collections.Generic;
+    using System.Diagnostics;
     using System.IdentityModel.Policy;
     using System.Net.Mail;
     using System.Security.Claims;
     using System.Security.Cryptography;
     using System.Security.Cryptography.X509Certificates;
     using System.Security.Principal;
+    using Globalization;
 
     public class X509CertificateClaimSet : ClaimSet, IIdentityInfo, IDisposable
     {
@@ -172,24 +174,7 @@ namespace System.IdentityModel.Claims
             if (!string.IsNullOrEmpty(value))
                 claims.Add(Claim.CreateX500DistinguishedNameClaim(this.certificate.SubjectName));
 
-            // App context switch for disabling support for multiple dns entries in a SAN certificate
-            if (LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate)
-            {
-                // old behavior, default for <= 4.6
-                value = this.certificate.GetNameInfo(X509NameType.DnsName, false);
-                if (!string.IsNullOrEmpty(value))
-                    claims.Add(Claim.CreateDnsClaim(value));
-            }
-            else
-            {
-                // new behavior as this is the default long term behavior
-                // Since a SAN can have multiple DNS entries
-                string[] entries = GetDnsFromExtensions(this.certificate);
-                for (int i = 0; i < entries.Length; ++i)
-                {
-                    claims.Add(Claim.CreateDnsClaim(entries[i]));
-                }
-            }
+            claims.AddRange(GetDnsClaims(this.certificate));
 
             value = this.certificate.GetNameInfo(X509NameType.SimpleName, false);
             if (!string.IsNullOrEmpty(value))
@@ -258,25 +243,8 @@ namespace System.IdentityModel.Claims
             {
                 if (right == null || Rights.PossessProperty.Equals(right))
                 {
-                    // App context switch for disabling support for multiple dns entries in a SAN certificate
-                    if (LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate)
-                    {
-                        // old behavior, default for <= 4.6
-                        string value = this.certificate.GetNameInfo(X509NameType.DnsName, false);
-                        if (!string.IsNullOrEmpty(value))
-                        {
-                            yield return Claim.CreateDnsClaim(value);
-                        }
-                    }
-                    else
-                    {
-                        // new behavior since this is the default long term behavior
-                        string[] entries = GetDnsFromExtensions(certificate);
-                        for (int i = 0; i < entries.Length; ++i)
-                        {
-                            yield return Claim.CreateDnsClaim(entries[i]);
-                        }
-                    }
+                    foreach (var claim in GetDnsClaims(certificate))
+                        yield return claim;
                 }
             }
             else
@@ -299,31 +267,44 @@ namespace System.IdentityModel.Claims
             }
         }
 
-        // Fixing Bug 795660: SAN having multiple DNS entries
-        private static string[] GetDnsFromExtensions(X509Certificate2 cert)
+        private static List<Claim> GetDnsClaims(X509Certificate2 cert)
         {
-            foreach (X509Extension ext in cert.Extensions)
+            List<Claim> dnsClaimEntries = new List<Claim>();
+
+            // old behavior, default for <= 4.6
+            string value = cert.GetNameInfo(X509NameType.DnsName, false);
+            if (!string.IsNullOrEmpty(value))
+                dnsClaimEntries.Add(Claim.CreateDnsClaim(value));
+
+            // App context switch for disabling support for multiple dns entries in a SAN certificate
+            // If we can't dynamically parse the alt subject names, we will not add any dns claims ONLY for the alt subject names.
+            // In this way, if the X509NameType.DnsName was enough to succeed for the out-bound-message. We would have a success.
+            if (!LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate && X509SubjectAlternativeNameConstants.SuccessfullyInitialized)
             {
-                // Extension is SAN or SAN2
-                if (ext.Oid.Value == "2.5.29.7" || ext.Oid.Value == "2.5.29.17")
+                foreach (X509Extension ext in cert.Extensions)
                 {
-                    string asnString = ext.Format(true);
-                    if (string.IsNullOrEmpty(asnString))
+                    // Extension is SAN or SAN2
+                    if (ext.Oid.Value == X509SubjectAlternativeNameConstants.SanOid || ext.Oid.Value == X509SubjectAlternativeNameConstants.San2Oid)
                     {
-                        return new string[0];
-                    }
-
-                    string[] rawDnsEntries = asnString.Split(new string[1] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
-                    string[] dnsEntries = new string[rawDnsEntries.Length];
-                    for (int i = 0; i < rawDnsEntries.Length; ++i)
-                    {
-                        int equalSignIndex = rawDnsEntries[i].IndexOf('=');
-                        dnsEntries[i] = rawDnsEntries[i].Substring(equalSignIndex + 1).Trim();
+                        string asnString = ext.Format(false);
+                        if (string.IsNullOrWhiteSpace(asnString))
+                            break;
+
+                        // SubjectAlternativeNames might contain something other than a dNSName, 
+                        // so we have to parse through and only use the dNSNames
+                        // <identifier><delimiter><value><separator(s)>
+                        string[] rawDnsEntries = asnString.Split(X509SubjectAlternativeNameConstants.SeparatorArray, StringSplitOptions.RemoveEmptyEntries);
+                        for (int i = 0; i < rawDnsEntries.Length; i++)
+                        {
+                            string[] keyval = rawDnsEntries[i].Split(X509SubjectAlternativeNameConstants.Delimiter);
+                            if (string.Equals(keyval[0], X509SubjectAlternativeNameConstants.Identifier))
+                                dnsClaimEntries.Add(Claim.CreateDnsClaim(keyval[1]));
+                        }
                     }
-                    return dnsEntries;
                 }
             }
-            return new string[0];
+
+            return dnsClaimEntries;
         }
 
         public override IEnumerator<Claim> GetEnumerator()
@@ -367,6 +348,107 @@ namespace System.IdentityModel.Claims
                 get { return this.identity; }
             }
         }
+
+        // We don't have a strongly typed extension to parse Subject Alt Names, so we have to do a workaround 
+        // to figure out what the identifier, delimiter, and separator is by using a well-known extension
+        private static class X509SubjectAlternativeNameConstants
+        {
+            public const string SanOid = "2.5.29.7";
+            public const string San2Oid = "2.5.29.17";
+
+            public static string Identifier
+            {
+                get;
+                private set;
+            }
+
+            public static char Delimiter
+            {
+                get;
+                private set;
+            }
+
+            public static string Separator
+            {
+                get;
+                private set;
+            }
+
+            public static string[] SeparatorArray
+            {
+                get;
+                private set;
+            }
+
+            public static bool SuccessfullyInitialized
+            {
+                get;
+                private set;
+            }
+
+            // static initializer will run before properties are accessed
+            static X509SubjectAlternativeNameConstants()
+            {
+                // Extracted a well-known X509Extension
+                byte[] x509ExtensionBytes = new byte[] {
+                    48, 36, 130, 21, 110, 111, 116, 45, 114, 101, 97, 108, 45, 115, 117, 98, 106, 101, 99,
+                    116, 45, 110, 97, 109, 101, 130, 11, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109
+                };
+                const string subjectName = "not-real-subject-name";
+                string x509ExtensionFormattedString = string.Empty;
+                try
+                {
+                    X509Extension x509Extension = new X509Extension(SanOid, x509ExtensionBytes, true);
+                    x509ExtensionFormattedString = x509Extension.Format(false);
+
+                    // Each OS has a different dNSName identifier and delimiter
+                    // On Windows, dNSName == "DNS Name" (localizable), on Linux, dNSName == "DNS"
+                    // e.g.,
+                    // Windows: x509ExtensionFormattedString is: "DNS Name=not-real-subject-name, DNS Name=example.com"
+                    // Linux:   x509ExtensionFormattedString is: "DNS:not-real-subject-name, DNS:example.com"
+                    // Parse: <identifier><delimiter><value><separator(s)>
+
+                    int delimiterIndex = x509ExtensionFormattedString.IndexOf(subjectName) - 1;
+                    Delimiter = x509ExtensionFormattedString[delimiterIndex];
+
+                    // Make an assumption that all characters from the the start of string to the delimiter 
+                    // are part of the identifier
+                    Identifier = x509ExtensionFormattedString.Substring(0, delimiterIndex);
+
+                    int separatorFirstChar = delimiterIndex + subjectName.Length + 1;
+                    int separatorLength = 1;
+                    for (int i = separatorFirstChar + 1; i < x509ExtensionFormattedString.Length; i++)
+                    {
+                        // We advance until the first character of the identifier to determine what the
+                        // separator is. This assumes that the identifier assumption above is correct
+                        if (x509ExtensionFormattedString[i] == Identifier[0])
+                        {
+                            break;
+                        }
+
+                        separatorLength++;
+                    }
+
+                    Separator = x509ExtensionFormattedString.Substring(separatorFirstChar, separatorLength);
+                    SeparatorArray = new string[1] { Separator };
+                    SuccessfullyInitialized = true;
+                }
+                catch (Exception ex)
+                {
+                    SuccessfullyInitialized = false;                    
+                    DiagnosticUtility.TraceHandledException(
+                        new FormatException(string.Format(CultureInfo.InvariantCulture,
+                        "There was an error parsing the SubjectAlternativeNames: '{0}'. See inner exception for more details.{1}Detected values were: Identifier: '{2}'; Delimiter:'{3}'; Separator:'{4}'",
+                        x509ExtensionFormattedString,
+                        Environment.NewLine,
+                        Identifier,
+                        Delimiter,
+                        Separator),
+                        ex), 
+                        TraceEventType.Warning);
+                }
+            }
+        }
     }
 
     class X509Identity : GenericIdentity, IDisposable
index f18ab5dd5824bbf60ee56a465b811217cd3f5877..b6bc822248a4ab80b622f4a052e70a37b5635d00 100644 (file)
@@ -15,9 +15,11 @@ namespace System.IdentityModel
     {
         private const string EnableCachedEmptyDefaultAuthorizationContextString = "Switch.System.IdentityModel.EnableCachedEmptyDefaultAuthorizationContext";
         private const string DisableMultipleDNSEntriesInSANCertificateString = "Switch.System.IdentityModel.DisableMultipleDNSEntriesInSANCertificate";
+        private const string DisableUpdatingRsaProviderTypeString = "Switch.System.IdentityModel.DisableUpdatingRsaProviderType";
 
         private static int enableCachedEmptyDefaultAuthorizationContext;
         private static int disableMultipleDNSEntriesInSANCertificate;
+        private static int disableUpdatingRsaProviderType;
 
         public static bool EnableCachedEmptyDefaultAuthorizationContext
         {
@@ -37,16 +39,29 @@ namespace System.IdentityModel
             }
         }
 
+        public static bool DisableUpdatingRsaProviderType
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return LocalAppContext.GetCachedSwitchValue(DisableUpdatingRsaProviderTypeString, ref disableUpdatingRsaProviderType);
+            }
+        }
+
         public static void SetDefaultsLessOrEqual_452()
         {
+#pragma warning disable BCL0012
             // Define the switches that should be true for 4.5.2 or less, false for 4.6+.
             LocalAppContext.DefineSwitchDefault(EnableCachedEmptyDefaultAuthorizationContextString, true);
+#pragma warning restore BCL0012
         }
 
         public static void SetDefaultsLessOrEqual_46()
         {
+#pragma warning disable BCL0012
             // Define the switches that should be true for 4.6 or less, false for 4.6.1+.
             LocalAppContext.DefineSwitchDefault(DisableMultipleDNSEntriesInSANCertificateString, true);
+#pragma warning restore BCL0012
         }
     }
 }
index 397194f64469e1e27eac88262308920f3dc5b204..fb1918c6ca6f823c3c159dda9906958fdd153b4b 100644 (file)
@@ -309,22 +309,26 @@ namespace System.IdentityModel.Tokens
             {
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.GetString(SR.EmptyOrNullArgumentString, "algorithm"));
             }
-            // We support one of the two algoritms, but not both.
+
+            // We support:
             //     XmlDsigDSAUrl = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
             //     XmlDsigRSASHA1Url = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
+            //     RsaSha256Signature = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
+            AsymmetricAlgorithm privateKey = LevelUpRsa(this.PrivateKey, algorithm);
+
             object algorithmObject = CryptoHelper.GetAlgorithmFromConfig(algorithm);
             if (algorithmObject != null)
             {
                 SignatureDescription description = algorithmObject as SignatureDescription;
                 if (description != null)
-                    return description.CreateFormatter(this.PrivateKey);
+                    return description.CreateFormatter(privateKey);
 
                 try
                 {
                     AsymmetricSignatureFormatter asymmetricSignatureFormatter = algorithmObject as AsymmetricSignatureFormatter;
                     if (asymmetricSignatureFormatter != null)
                     {
-                        asymmetricSignatureFormatter.SetKey(this.PrivateKey);
+                        asymmetricSignatureFormatter.SetKey(privateKey);
                         return asymmetricSignatureFormatter;
                     }
                 }
@@ -356,19 +360,10 @@ namespace System.IdentityModel.Tokens
 
                 case SecurityAlgorithms.RsaSha256Signature:
                     // Ensure that we have an RSA algorithm object.
-                    RSACryptoServiceProvider rsa_prov_full = (this.PrivateKey as RSACryptoServiceProvider);
-                    if (rsa_prov_full == null)
+                    RSA rsaSha256 = (privateKey as RSA);
+                    if (rsaSha256 == null)
                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.PrivateKeyNotRSA)));
-                    CspParameters csp = new CspParameters();
-                    csp.ProviderType = 24;
-                    csp.KeyContainerName = rsa_prov_full.CspKeyContainerInfo.KeyContainerName;
-                    csp.KeyNumber = (int)rsa_prov_full.CspKeyContainerInfo.KeyNumber;
-                    if (rsa_prov_full.CspKeyContainerInfo.MachineKeyStore)
-                        csp.Flags = CspProviderFlags.UseMachineKeyStore;
-                    
-                    csp.Flags |= CspProviderFlags.UseExistingKey;
-
-                    return new RSAPKCS1SignatureFormatter(new RSACryptoServiceProvider(csp));
+                    return new RSAPKCS1SignatureFormatter(rsaSha256);
 
                 default:
                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedCryptoAlgorithm, algorithm)));
@@ -376,6 +371,45 @@ namespace System.IdentityModel.Tokens
 
         }
 
+        private static AsymmetricAlgorithm LevelUpRsa(AsymmetricAlgorithm asymmetricAlgorithm, string algorithm)
+        {
+            // If user turned off leveling up at app level, return
+            if (LocalAppContextSwitches.DisableUpdatingRsaProviderType)
+                return asymmetricAlgorithm;
+
+            if (asymmetricAlgorithm == null)
+                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("asymmetricAlgorithm"));
+
+            if (string.IsNullOrEmpty(algorithm))
+                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.GetString(SR.EmptyOrNullArgumentString, "algorithm"));
+
+            // only level up if alg is sha256
+            if (!string.Equals(algorithm, SecurityAlgorithms.RsaSha256Signature))
+                return asymmetricAlgorithm;
+
+            RSACryptoServiceProvider rsaCsp = asymmetricAlgorithm as RSACryptoServiceProvider;
+            if (rsaCsp == null)
+                return asymmetricAlgorithm;
+
+            // ProviderType == 1(PROV_RSA_FULL) and providerType == 12(PROV_RSA_SCHANNEL) are provider types that only support SHA1. Change them to PROV_RSA_AES=24 that supports SHA2 also.
+            // Only levels up if the associated key is not a hardware key.
+            // Another provider type related to rsa, PROV_RSA_SIG == 2 that only supports Sha1 is no longer supported
+            if ((rsaCsp.CspKeyContainerInfo.ProviderType == 1 || rsaCsp.CspKeyContainerInfo.ProviderType == 12) && !rsaCsp.CspKeyContainerInfo.HardwareDevice)
+            {
+                CspParameters csp = new CspParameters();
+                csp.ProviderType = 24;
+                csp.KeyContainerName = rsaCsp.CspKeyContainerInfo.KeyContainerName;
+                csp.KeyNumber = (int)rsaCsp.CspKeyContainerInfo.KeyNumber;
+                if (rsaCsp.CspKeyContainerInfo.MachineKeyStore)
+                    csp.Flags = CspProviderFlags.UseMachineKeyStore;
+
+                csp.Flags |= CspProviderFlags.UseExistingKey;
+                return new RSACryptoServiceProvider(csp);
+            }
+
+            return rsaCsp;
+        }
+
         public override bool HasPrivateKey()
         {
             return (this.PrivateKey != null);
index 8b32bedf742df80aaeba5119b2d5a6c05aba5524..05af1435998d748e0440081b5e4fab813001612f 100644 (file)
@@ -27,7 +27,7 @@ namespace System.Runtime.Caching {
         private long[] _cacheSizeSamples;
         private DateTime[] _cacheSizeSampleTimes;
         private int _idx;
-        private SRef _sizedRef;
+        private SRefMultiple _sizedRefMultiple;
         private int _gen2Count;
         private long _memoryLimit;
 
@@ -51,7 +51,7 @@ namespace System.Runtime.Caching {
         private void InitDisposableMembers(int cacheMemoryLimitMegabytes) {
             bool dispose = true;
             try {
-                _sizedRef = new SRef(_memoryCache);
+                _sizedRefMultiple = new SRefMultiple(_memoryCache.AllSRefTargets);
                 SetLimit(cacheMemoryLimitMegabytes);
                 InitHistory();
                 dispose = false;
@@ -112,8 +112,8 @@ namespace System.Runtime.Caching {
         }
 
         public void Dispose() {
-            SRef sref = _sizedRef;
-            if (sref != null && Interlocked.CompareExchange(ref _sizedRef, null, sref) == sref) {
+            SRefMultiple sref = _sizedRefMultiple;
+            if (sref != null && Interlocked.CompareExchange(ref _sizedRefMultiple, null, sref) == sref) {
                 sref.Dispose();
             }
             IMemoryCacheManager memoryCacheManager = s_memoryCacheManager;
@@ -139,7 +139,7 @@ namespace System.Runtime.Caching {
             // This update must happen, otherwise the CacheManager won't 
             // know the total cache size.
             int gen2Count = GC.CollectionCount(2);
-            SRef sref = _sizedRef;
+            SRefMultiple sref = _sizedRefMultiple;
             if (gen2Count != _gen2Count && sref != null) {
                 // update _gen2Count
                 _gen2Count = gen2Count;
index 816319755cb9a6ba3d5fe0d93211753585a1c8b4..f74996a20e11cfb99afd0ed2079fcf23fd69a3cc 100644 (file)
@@ -27,9 +27,8 @@ namespace System.Runtime.Caching {
         private static object s_initLock = new object();
         private static MemoryCache s_defaultCache;
         private static CacheEntryRemovedCallback s_sentinelRemovedCallback = new CacheEntryRemovedCallback(SentinelEntry.OnCacheEntryRemovedCallback);
-        private MemoryCacheStore[] _stores;
+        private GCHandleRef<MemoryCacheStore>[] _storeRefs;
         private int _storeCount;
-        private int _storeMask;
         private int _disposed;
         private MemoryCacheStatistics _stats;
         private string _name;
@@ -150,8 +149,18 @@ namespace System.Runtime.Caching {
             if (hashCode < 0) {
                 hashCode = (hashCode == Int32.MinValue) ? 0 : -hashCode;
             }
-            int idx = hashCode & _storeMask;
-            return _stores[idx];
+            int idx = hashCode % _storeCount;
+            return _storeRefs[idx].Target;
+        }
+
+        internal object[] AllSRefTargets {
+            get {
+                var allStores = new MemoryCacheStore[_storeCount];
+                for (int i = 0; i < _storeCount; i++) {
+                    allStores[i] = _storeRefs[i].Target;
+                }
+                return allStores;
+            }
         }
 
         [SecuritySafeCritical]
@@ -166,8 +175,8 @@ namespace System.Runtime.Caching {
                 catch {
                     // ignore exceptions from perf counters
                 }
-                for (int i = 0; i < _stores.Length; i++) {
-                    _stores[i] = new MemoryCacheStore(this, _perfCounters);
+                for (int i = 0; i < _storeCount; i++) {
+                    _storeRefs[i] = new GCHandleRef<MemoryCacheStore> (new MemoryCacheStore(this, _perfCounters));
                 }
                 _stats = new MemoryCacheStatistics(this, config);
                 AppDomain appDomain = Thread.GetDomain();
@@ -321,8 +330,7 @@ namespace System.Runtime.Caching {
                 }
             }
 #endif
-            _storeMask = _storeCount - 1;
-            _stores = new MemoryCacheStore[_storeCount];
+            _storeRefs = new GCHandleRef<MemoryCacheStore>[_storeCount];
             InitDisposableMembers(config);
         }
 
@@ -392,10 +400,10 @@ namespace System.Runtime.Caching {
                 if (_stats != null) {
                     _stats.Dispose();
                 }
-                if (_stores != null) {
-                    foreach (MemoryCacheStore store in _stores) {
-                        if (store != null) {
-                            store.Dispose();
+                if (_storeRefs != null) {
+                    foreach (var storeRef in _storeRefs) {
+                        if (storeRef != null) {
+                            storeRef.Dispose();
                         }
                     }
                 }
@@ -442,8 +450,8 @@ namespace System.Runtime.Caching {
         IEnumerator IEnumerable.GetEnumerator() {
             Hashtable h = new Hashtable();
             if (!IsDisposed) {
-                foreach (MemoryCacheStore store in _stores) {
-                    store.CopyTo(h);
+                foreach (var storeRef in _storeRefs) {
+                    storeRef.Target.CopyTo(h);
                 }
             }
             return h.GetEnumerator();
@@ -452,8 +460,8 @@ namespace System.Runtime.Caching {
         protected override IEnumerator<KeyValuePair<string, object>> GetEnumerator() {
             Dictionary<string, object> h = new Dictionary<string, object>();
             if (!IsDisposed) {
-                foreach (MemoryCacheStore store in _stores) {
-                    store.CopyTo(h);
+                foreach (var storeRef in _storeRefs) {
+                    storeRef.Target.CopyTo(h);
                 }
             }
             return h.GetEnumerator();
@@ -471,8 +479,8 @@ namespace System.Runtime.Caching {
             }
             long trimmed = 0;
             if (_disposed == 0) {
-                foreach (MemoryCacheStore store in _stores) {
-                    trimmed += store.TrimInternal(percent);
+                foreach (var storeRef in _storeRefs) {
+                    trimmed += storeRef.Target.TrimInternal(percent);
                 }
             }
             return trimmed;
@@ -680,8 +688,8 @@ namespace System.Runtime.Caching {
             }
             long count = 0;
             if (!IsDisposed) {
-                foreach (MemoryCacheStore store in _stores) {
-                    count += store.Count;
+                foreach (var storeRef in _storeRefs) {
+                    count += storeRef.Target.Count;
                 }
             }
             return count;
index 61d3ce3ace7fe6afb598662aa5e4d3aa046020f6..99196c05f5d90ee6dd78ad6478fb673f26680b88 100644 (file)
@@ -27,7 +27,7 @@ namespace System.Runtime.Caching {
         private int _lastTrimPercent;
         private DateTime _lastTrimTime;        
         private int _pollingInterval;
-        private Timer _timer;
+        private GCHandleRef<Timer> _timerHandleRef;
         private Object _timerLock;
         private long _totalCountBeforeTrim;
 
@@ -44,16 +44,18 @@ namespace System.Runtime.Caching {
         private void AdjustTimer() {
             lock (_timerLock) {
 
-                if (_timer == null)
+                if (_timerHandleRef == null)
                     return;
 
+                Timer timer = _timerHandleRef.Target;
+
                 // the order of these if statements is important
 
                 // When above the high pressure mark, interval should be 5 seconds or less
                 if (_physicalMemoryMonitor.IsAboveHighPressure() || _cacheMemoryMonitor.IsAboveHighPressure()) {
                     if (_pollingInterval > MEMORYSTATUS_INTERVAL_5_SECONDS) {
                         _pollingInterval = MEMORYSTATUS_INTERVAL_5_SECONDS;
-                        _timer.Change(_pollingInterval, _pollingInterval);
+                        timer.Change(_pollingInterval, _pollingInterval);
                     }
                     return;
                 }
@@ -65,7 +67,7 @@ namespace System.Runtime.Caching {
                     int newPollingInterval = Math.Min(_configPollingInterval, MEMORYSTATUS_INTERVAL_30_SECONDS);
                     if (_pollingInterval != newPollingInterval) {
                         _pollingInterval = newPollingInterval;
-                        _timer.Change(_pollingInterval, _pollingInterval);
+                        timer.Change(_pollingInterval, _pollingInterval);
                     }
                     return;
                 }
@@ -73,7 +75,7 @@ namespace System.Runtime.Caching {
                 // there is no pressure, interval should be the value from config
                 if (_pollingInterval != _configPollingInterval) {
                     _pollingInterval = _configPollingInterval;
-                    _timer.Change(_pollingInterval, _pollingInterval);
+                    timer.Change(_pollingInterval, _pollingInterval);
                 }
             }
         }
@@ -126,7 +128,8 @@ namespace System.Runtime.Caching {
             bool dispose = true;
             try {
                 _cacheMemoryMonitor = new CacheMemoryMonitor(_memoryCache, _configCacheMemoryLimitMegabytes);
-                _timer = new Timer(new TimerCallback(CacheManagerTimerCallback), null, _configPollingInterval, _configPollingInterval);
+                Timer timer = new Timer(new TimerCallback(CacheManagerTimerCallback), null, _configPollingInterval, _configPollingInterval);
+                _timerHandleRef = new GCHandleRef<Timer>(timer);
                 dispose = false;
             }
             finally {
@@ -246,9 +249,9 @@ namespace System.Runtime.Caching {
         public void Dispose() {
             if (Interlocked.Exchange(ref _disposed, 1) == 0) {
                 lock (_timerLock) {
-                    Timer timer = _timer;
-                    if (timer != null && Interlocked.CompareExchange(ref _timer, null, timer) == timer) {
-                        timer.Dispose();
+                    GCHandleRef<Timer> timerHandleRef = _timerHandleRef;
+                    if (timerHandleRef != null && Interlocked.CompareExchange(ref _timerHandleRef, null, timerHandleRef) == timerHandleRef) {
+                        timerHandleRef.Dispose();
                         Dbg.Trace("MemoryCacheStats", "Stopped CacheMemoryTimers");
                     }
                 }
index 27ee134e46e8f5fc6ba8775e92d3689a8fdb2fec..50374308bafd044687a2c868fb025e1b56591d3d 100644 (file)
@@ -7,24 +7,33 @@ using System.Reflection;
 using System.Security;
 using System.Security.Permissions;
 using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
 
 namespace System.Runtime.Caching {
     internal class SRef {
+#if !MONO
         private static Type s_type = Type.GetType("System.SizedReference", true, false);
         private Object _sizedRef;
+#endif
 
         internal SRef(Object target) {
+#if !MONO
             _sizedRef = Activator.CreateInstance(s_type,
                     BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance,
                     null,
                     new object[] { target },
                     null);
+#endif
         }
 
         internal long ApproximateSize {
             [SecuritySafeCritical]
             [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
             get {
+#if MONO
+                // TODO: .net uses System.SizedReference which contains approximate size after Gen 2 collection
+                return 16;
+#else
                 object o = s_type.InvokeMember("ApproximateSize",
                                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
                                                null, // binder
@@ -32,6 +41,7 @@ namespace System.Runtime.Caching {
                                                null, // args
                                                CultureInfo.InvariantCulture);
                 return (long)o;
+#endif
             }
         }
 
@@ -40,12 +50,87 @@ namespace System.Runtime.Caching {
         [SecuritySafeCritical]
         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
         internal void Dispose() {
+#if !MONO
             s_type.InvokeMember("Dispose",
                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
                                 null, // binder
                                 _sizedRef, // target
                                 null, // args
                                 CultureInfo.InvariantCulture);
+#endif
+        }
+    }
+
+    internal class SRefMultiple {
+        private SRef[] _srefs;
+        private long[] _sizes;  // Getting SRef size in the debugger is extremely tedious so we keep the last read value here
+
+        internal SRefMultiple(object[] targets) {
+            _srefs = new SRef[targets.Length];
+            _sizes = new long[targets.Length];
+            for (int i = 0; i < targets.Length; i++) {
+                _srefs[i] = new SRef(targets[i]);
+            }
+        }
+
+        internal long ApproximateSize {
+            get {
+                long size = 0;
+                for (int i = 0; i < _srefs.Length; i++) {
+                    size += (_sizes[i] = _srefs[i].ApproximateSize);
+                }
+                return size;
+            }
+        }
+
+        internal void Dispose() {
+            foreach (SRef s in _srefs) {
+                s.Dispose();
+            }
+        }
+    }
+
+    internal class GCHandleRef<T> : IDisposable
+    where T : class, IDisposable {
+        GCHandle _handle;
+        T _t;
+
+        [SecuritySafeCritical]
+        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+        public GCHandleRef(T t) {
+            _handle = GCHandle.Alloc(t);
+        }
+
+        public T Target {
+            [SecuritySafeCritical]
+            [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+            get {
+                try { 
+                    T t = (T)_handle.Target;
+                    if (t != null) {
+                        return t;
+                    }
+                }
+                catch (InvalidOperationException) {
+                    // use the normal reference instead of throwing an exception when _handle is already freed
+                }
+                return _t;
+            }
+        }
+
+        [SecuritySafeCritical]
+        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+        public void Dispose() {
+            Target.Dispose();
+            // Safe to call Dispose more than once but not thread-safe
+            if (_handle.IsAllocated) {
+                // We must free the GC handle to avoid leaks.
+                // However after _handle is freed we no longer have access to its Target
+                // which will cause AVs and various race conditions under stress.
+                // We revert to using normal references after disposing the GC handle
+                _t = (T)_handle.Target;
+                _handle.Free();
+            }
         }
     }
 }
index c63c76f91537ad23db1f24fb585d429c313200cd..2ed1d48643d071051cbb40b991b398d60b8f2f8f 100644 (file)
@@ -458,7 +458,8 @@ namespace System.Runtime.Serialization
                 if (dataContract == null)
                 {
                     dataContract = CreateGetOnlyCollectionDataContract(id, typeHandle, type);
-                    dataContractCache[id] = dataContract;
+
+                    AssignDataContractToId(dataContract, id);
                 }
                 return dataContract;
             }
@@ -480,7 +481,10 @@ namespace System.Runtime.Serialization
                 {
                     return id;
                 }
-                for (int i = 0; i < DataContractCriticalHelper.dataContractID; i++)
+
+                int currentDataContractId = DataContractCriticalHelper.dataContractID;
+
+                for (int i = 0; i < currentDataContractId; i++)
                 {
                     if (ContractMatches(classContract, dataContractCache[i]))
                     {
@@ -542,49 +546,66 @@ namespace System.Runtime.Serialization
             // check whether a corresponding update is required in ClassDataContract.IsNonAttributedTypeValidForSerialization
             static DataContract CreateDataContract(int id, RuntimeTypeHandle typeHandle, Type type)
             {
-                lock (createDataContractLock)
+                DataContract dataContract = dataContractCache[id];
+
+                if (dataContract == null)
                 {
-                    DataContract dataContract = dataContractCache[id];
-                    if (dataContract == null)
+                    lock (createDataContractLock)
                     {
-                        if (type == null)
-                            type = Type.GetTypeFromHandle(typeHandle);
-                        type = UnwrapNullableType(type);
-                        type = GetDataContractAdapterType(type);
-                        dataContract = GetBuiltInDataContract(type);
+                        dataContract = dataContractCache[id];
+
                         if (dataContract == null)
                         {
-                            if (type.IsArray)
-                                dataContract = new CollectionDataContract(type);
-                            else if (type.IsEnum)
-                                dataContract = new EnumDataContract(type);
-                            else if (type.IsGenericParameter)
-                                dataContract = new GenericParameterDataContract(type);
-                            else if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
-                                dataContract = new XmlDataContract(type);
-                            else
+                            if (type == null)
+                                type = Type.GetTypeFromHandle(typeHandle);
+                            type = UnwrapNullableType(type);
+                            type = GetDataContractAdapterType(type);
+                            dataContract = GetBuiltInDataContract(type);
+                            if (dataContract == null)
                             {
-                                //if (type.ContainsGenericParameters)
-                                //    ThrowInvalidDataContractException(SR.GetString(SR.TypeMustNotBeOpenGeneric, type), type);
-                                if (type.IsPointer)
-                                    type = Globals.TypeOfReflectionPointer;
-
-                                if (!CollectionDataContract.TryCreate(type, out dataContract))
+                                if (type.IsArray)
+                                    dataContract = new CollectionDataContract(type);
+                                else if (type.IsEnum)
+                                    dataContract = new EnumDataContract(type);
+                                else if (type.IsGenericParameter)
+                                    dataContract = new GenericParameterDataContract(type);
+                                else if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
+                                    dataContract = new XmlDataContract(type);
+                                else
                                 {
-                                    if (type.IsSerializable || type.IsDefined(Globals.TypeOfDataContractAttribute, false) || ClassDataContract.IsNonAttributedTypeValidForSerialization(type))
-                                    {
-                                        dataContract = new ClassDataContract(type);
-                                    }
-                                    else
+                                    //if (type.ContainsGenericParameters)
+                                    //    ThrowInvalidDataContractException(SR.GetString(SR.TypeMustNotBeOpenGeneric, type), type);
+                                    if (type.IsPointer)
+                                        type = Globals.TypeOfReflectionPointer;
+
+                                    if (!CollectionDataContract.TryCreate(type, out dataContract))
                                     {
-                                        ThrowInvalidDataContractException(SR.GetString(SR.TypeNotSerializable, type), type);
+                                        if (type.IsSerializable || type.IsDefined(Globals.TypeOfDataContractAttribute, false) || ClassDataContract.IsNonAttributedTypeValidForSerialization(type))
+                                        {
+                                            dataContract = new ClassDataContract(type);
+                                        }
+                                        else
+                                        {
+                                            ThrowInvalidDataContractException(SR.GetString(SR.TypeNotSerializable, type), type);
+                                        }
                                     }
                                 }
                             }
-                        }
+
+                            AssignDataContractToId(dataContract, id);
+                        }                        
                     }
+                }
+
+                return dataContract;
+            }
+
+            [MethodImpl(MethodImplOptions.NoInlining)]
+            static void AssignDataContractToId(DataContract dataContract, int id)
+            {
+                lock (cacheLock)
+                {
                     dataContractCache[id] = dataContract;
-                    return dataContract;
                 }
             }
 
@@ -1200,7 +1221,8 @@ namespace System.Runtime.Serialization
 
                         parseMethodSet = true;
                     }
-                    return parseMethod; }
+                    return parseMethod;
+                }
             }
 
             internal virtual void WriteRootElement(XmlWriterDelegator writer, XmlDictionaryString name, XmlDictionaryString ns)
index 54f0f3fa0955228a4e7e6461966df61615fea011..6e0e98201fe62e868e7763fcbbf6987d9bef9c9c 100644 (file)
@@ -204,7 +204,15 @@ namespace System.Runtime.Serialization.Json
             // This will break round-tripping of these dates (see bug 9690 in CSD Developer Framework)
             if (value.Kind != DateTimeKind.Utc)
             {
-                long tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks;
+                long tickCount;
+                if (!LocalAppContextSwitches.DoNotUseTimeZoneInfo)
+                {
+                    tickCount = value.Ticks - TimeZoneInfo.Local.GetUtcOffset(value).Ticks;
+                }
+                else
+                {
+                    tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks;
+                }
                 if ((tickCount > DateTime.MaxValue.Ticks) || (tickCount < DateTime.MinValue.Ticks))
                 {
                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
@@ -220,7 +228,15 @@ namespace System.Runtime.Serialization.Json
                 case DateTimeKind.Unspecified:
                 case DateTimeKind.Local:
                     // +"zzzz";
-                    TimeSpan ts = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime());
+                    TimeSpan ts;
+                    if (!LocalAppContextSwitches.DoNotUseTimeZoneInfo)
+                    {
+                        ts = TimeZoneInfo.Local.GetUtcOffset(value.ToLocalTime());
+                    }
+                    else
+                    {
+                        ts = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime());
+                    }
                     if (ts.Ticks < 0)
                     {
                         writer.WriteString("-");
index b2c4586e3bb8986e4d78bd7785f31e2a89b6b60b..ff5704a55dfb05d5c352da97a6f54a34984c9bc7 100644 (file)
@@ -75,7 +75,7 @@ namespace System.Runtime.Serialization
             if (!Schemas.Contains(Globals.SerializationNamespace))
             {
                 StringReader reader = new StringReader(Globals.SerializationSchema);
-                XmlSchema schema = XmlSchema.Read(reader, null);
+                XmlSchema schema = XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
                 if (schema == null)
                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CouldNotReadSerializationSchema, Globals.SerializationNamespace)));
                 Schemas.Add(schema);
index 32d06e427d250db300934fe20f13319a10537ac0..29885641acc94a669d874bf11eb345e4528915ec 100644 (file)
@@ -51,7 +51,7 @@ namespace System.Runtime.Serialization
             if (!schemaSet.Contains(Globals.SerializationNamespace))
             {
                 StringReader reader = new StringReader(Globals.SerializationSchema);
-                XmlSchema schema = XmlSchema.Read(reader, null);
+                XmlSchema schema = XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
                 if (schema == null)
                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CouldNotReadSerializationSchema, Globals.SerializationNamespace)));
                 schemaSet.Add(schema);
index c0dc0f32928e0bdb9fa2c8b8d3363068b88bd5ce..4e785e5b1ff9479d9e29a1a011c39d7b66791b93 100644 (file)
@@ -101,20 +101,13 @@ namespace System.ServiceModel.Activation
             }
         }
 
-        // Provides the version of the WebSocket protocol supported by IIS. Throws an exception if called before we determined the value.
+        // Provides the version of the WebSocket protocol supported by IIS.
         // Returns null if WebSockets are not supported (because the IIS WebSocketModule is not installed or enabled).
         public override string WebSocketVersion
         {
             get
             {
-                if (isWebSocketVersionSet)
-                {
-                    return webSocketVersion;
-                }
-                else
-                {
-                    throw Fx.AssertAndFailFast("The supported WebSocket protocol version is not determined at this time.");
-                }
+                return isWebSocketVersionSet ? webSocketVersion : null;
             }
         }
 
@@ -136,8 +129,6 @@ namespace System.ServiceModel.Activation
         /// </remarks>
         public static void TrySetWebSocketVersion(HttpApplication application)
         {
-            Fx.Assert(application != null, "Invalid argument.");
-
             if (!isWebSocketVersionSet)
             {
                 webSocketVersion = application.Request.ServerVariables[WebSocketVersionServerProperty];
index 4a81f353ca1d4f50f0f64789b02dba9d45568ff8..c84160682a5b24e941bd9a3aba64ddf6b1c87da0 100644 (file)
@@ -288,6 +288,7 @@ namespace System.Runtime.Diagnostics
 
         [Fx.Tag.SecurityNote(Critical = "Usage of EventDescriptor, which is protected by a LinkDemand")]
         [SecurityCritical]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml", Justification = "It is internal code. No security concern.")]
         public void WriteTraceSource(ref EventDescriptor eventDescriptor, string description, TracePayload payload)
         {
             if (this.TracingEnabled)
index 8a130a0f34285449d7dc69480eff98e832bf3edd..9224bf8b8fbac5bb40399ab2c13c752e3f0fd57f 100644 (file)
@@ -3,6 +3,15 @@
 //   Copyright (c) Microsoft Corporation.  All rights reserved.
 // 
 // ==--==
+
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 using System;
 using System.Collections.Generic;
 
@@ -167,3 +176,5 @@ namespace System
         static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
     }
 }
+
+#pragma warning restore 436
index f05b599ed3d2b9af36cb7cd29c3c39123370cf6e..33662b54280621d4ef98247f98badecf87773fda 100644 (file)
@@ -4,6 +4,14 @@
 // 
 // ==--==
 
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches
 using System;
 using System.Collections.Generic;
@@ -126,3 +134,5 @@ namespace System
         }
     }
 }
+
+#pragma warning restore 436
index 5f591137e3990ebb94efbdde1a260ea11cbebad1..e086fad2760ef4c41ac4e3e5bc158e4f525eb26e 100644 (file)
@@ -27,6 +27,11 @@ namespace System
                         LocalAppContextSwitches.SetDefaultsLessOrEqual_452();
                     }
 
+                    if (version <= 40601)
+                    {
+                        LocalAppContextSwitches.SetDefaultsLessOrEqual_461();
+                    }
+
                     break;
                 }
             }
index 785a9c05951269acd74c7d6f3efc8099e83eb1cd..5dac93babe149d98d661584dd61069d77207ab5e 100644 (file)
@@ -839,17 +839,11 @@ namespace System.ServiceModel.Channels
                 {
                     AspNetEnvironment env = AspNetEnvironment.Current;
 
-                    // When IIS hosted, WebSockets can be used if the pipeline mode is integrated and the WebSocketModule is loaded.
-                    // Otherwise, the client requests will not be upgraded to web sockets (see the code in HostedHttpTransportManager.HttpContextReceived(..)).
-                    // We do the checks below (and fail the service activation), to avoid starting a WebSockets listener that won't get called.
+                    // When IIS hosted, WebSockets can be used if the pipeline mode is integrated
                     if (!env.UsingIntegratedPipeline)
                     {
                         throw FxTrace.Exception.AsError(new NotSupportedException(SR.GetString(SR.WebSocketsNotSupportedInClassicPipeline)));
                     }
-                    else if (!env.IsWebSocketModuleLoaded)
-                    {
-                        throw FxTrace.Exception.AsError(new NotSupportedException(SR.GetString(SR.WebSocketModuleNotLoaded)));
-                    }
                 }
                 else if (!WebSocketHelper.OSSupportsWebSockets())
                 {
index f50e3667174e51a9ed111f895086c89240f0296c..ee3fbc127a7fcb92e6aa44345193357a75edc7ee 100644 (file)
@@ -6,6 +6,7 @@ namespace System.ServiceModel.Channels
 {
     using System.Collections.Generic;
     using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.IO;
     using System.Net;
@@ -1684,6 +1685,9 @@ namespace System.ServiceModel.Channels
             // then the Exact HostName, and lastly the WeakWildcard
             string[] hostChoices = new string[] { "+", uri.Host, "*" };
             bool[] globalChoices = new bool[] { true, false };
+            string matchPath = String.Empty;
+            string matchPipeName = null;
+
             for (int i = 0; i < hostChoices.Length; i++)
             {
                 for (int iGlobal = 0; iGlobal < globalChoices.Length; iGlobal++)
@@ -1696,7 +1700,7 @@ namespace System.ServiceModel.Channels
                         continue;
                     }
 
-                    // walk up the path hierarchy, looking for first match
+                    // walk up the path hierarchy, looking for match
                     string path = PipeUri.GetPath(uri);
 
                     while (path.Length > 0)
@@ -1713,7 +1717,21 @@ namespace System.ServiceModel.Channels
                                     string pipeName = sharedMemory.GetPipeName(appInfo);
                                     if (pipeName != null)
                                     {
-                                        return pipeName;
+                                        // Found a matching pipe name. 
+                                        // If the best match app setting is enabled, save the match if it is the best so far and continue.
+                                        // Otherwise, just return the first match we find.
+                                        if (ServiceModelAppSettings.UseBestMatchNamedPipeUri)
+                                        {
+                                            if (path.Length > matchPath.Length)
+                                            {
+                                                matchPath = path;
+                                                matchPipeName = pipeName;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            return pipeName;
+                                        }
                                     }
                                 }
                                 finally
@@ -1733,9 +1751,14 @@ namespace System.ServiceModel.Channels
                 }
             }
 
-            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
-                new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, uri.AbsoluteUri),
-                new PipeException(SR.GetString(SR.PipeEndpointNotFound, uri.AbsoluteUri))));
+            if (string.IsNullOrEmpty(matchPipeName))
+            {
+                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
+                    new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, uri.AbsoluteUri),
+                    new PipeException(SR.GetString(SR.PipeEndpointNotFound, uri.AbsoluteUri))));
+            }
+
+            return matchPipeName;
         }
 
         public IAsyncResult BeginConnect(Uri uri, TimeSpan timeout, AsyncCallback callback, object state)
@@ -1758,7 +1781,6 @@ namespace System.ServiceModel.Channels
                     new StringTraceRecord("Uri", remoteUri.ToString()), this, null);
             }
             resolvedAddress = GetPipeName(remoteUri, this.pipeSettings);
-
             const int backoffBufferMilliseconds = 150;
             TimeSpan backoffTimeout;
             if (timeout >= TimeSpan.FromMilliseconds(backoffBufferMilliseconds * 2))
@@ -2815,6 +2837,7 @@ namespace System.ServiceModel.Channels
             return builder.ToString();
         }
 
+        [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:DoNotUseSHA1", Justification = "Cannot change. It will cause compatibility issue. Not used for cryptographic purposes.")]
         static HashAlgorithm GetHashAlgorithm()
         {
             if (SecurityUtilsEx.RequiresFipsCompliance)
index 4de327474f770e27ff9dc283b5b29c3faa801dec..d2c0f72a516e3a6eb97d82efbc7043f9b7fc665a 100644 (file)
@@ -202,8 +202,8 @@ namespace System.ServiceModel.Channels
         internal const bool RequireClientCertificate = false;
         internal const int MaxFaultSize = MaxBufferSize;
         internal const int MaxSecurityFaultSize = 16384;
-        internal const SslProtocols SslProtocols = System.Security.Authentication.SslProtocols.Ssl3 |
-                                                   System.Security.Authentication.SslProtocols.Tls |
+
+        internal const SslProtocols SslProtocols = System.Security.Authentication.SslProtocols.Tls |
                                                    System.Security.Authentication.SslProtocols.Tls11 |
                                                    System.Security.Authentication.SslProtocols.Tls12;
 
index bade3dab69e91693e91f69fb8f9547151fcaf850..275270b401c80192f83133e0426810ac3eaa2c34 100644 (file)
@@ -1101,31 +1101,82 @@ namespace System.ServiceModel.Channels
 
 
 #if !FEATURE_CORECLR
-        // On CoreCLR this is not the way to determine if a process is a tailored application (which means APPX).
-        // On CoreCLR AppX is determined by a flag past to the host which is exposed by AppDomain.IsAppXProcess in mscorlib.
-        // The reason for this if-def is to ensure nobody takes a dependency on this on CoreCLR.
-        
+        private static IntPtr GetCurrentProcessToken() { return new IntPtr(-4); }
+
+        enum AppPolicyClrCompat
+        {
+            AppPolicyClrCompat_Others = 0,
+            AppPolicyClrCompat_ClassicDesktop = 1,
+            AppPolicyClrCompat_Universal = 2,
+            AppPolicyClrCompat_PackagedDesktop = 3
+        };
+
+        [DllImport(KERNEL32, CharSet = CharSet.None, EntryPoint = "AppPolicyGetClrCompat")]
+        [System.Security.SecuritySafeCritical]
+        [return: MarshalAs(UnmanagedType.I4)]
+        private static extern Int32 _AppPolicyGetClrCompat(IntPtr processToken, out AppPolicyClrCompat appPolicyClrCompat);
+
         // AppModel.h functions (Win8+)
         [DllImport(KERNEL32, CharSet = CharSet.None, EntryPoint = "GetCurrentPackageId")]
-        [SecurityCritical]
+        [System.Security.SecuritySafeCritical]
         [return: MarshalAs(UnmanagedType.I4)]
-        private static extern Int32 GetCurrentPackageId(ref Int32 pBufferLength, Byte[] pBuffer);
+        private static extern Int32 _GetCurrentPackageId(ref Int32 pBufferLength, Byte[] pBuffer);
 
-        [Fx.Tag.SecurityNote(
-            Critical = "Critical because it calls the native function GetCurrentPackageId.",
-            Safe = "Safe because it takes no user input and it doesn't leak security sensitive information.")]
-        [SecuritySafeCritical]
+        [DllImport(KERNEL32, CharSet=System.Runtime.InteropServices.CharSet.Auto, BestFitMapping=false)]
+        [ResourceExposure(ResourceScope.Machine)]
+        private static extern IntPtr GetModuleHandle(string modName);
+
+        // Copied from Win32Native.cs
+        // Note - do NOT use this to call methods.  Use P/Invoke, which will
+        // do much better things w.r.t. marshaling, pinning memory, security 
+        // stuff, better interactions with thread aborts, etc.  This is used
+        // solely by DoesWin32MethodExist for avoiding try/catch EntryPointNotFoundException
+        // in scenarios where an OS Version check is insufficient
+        [DllImport(KERNEL32, CharSet=CharSet.Ansi, BestFitMapping=false, SetLastError=true, ExactSpelling=true)]
+        [ResourceExposure(ResourceScope.None)]
+        private static extern IntPtr GetProcAddress(IntPtr hModule, String methodName);
+
+        [System.Security.SecurityCritical]  // auto-generated
+        private static bool DoesWin32MethodExist(String moduleName, String methodName)
+        {
+            // GetModuleHandle does not increment the module's ref count, so we don't need to call FreeLibrary.
+            IntPtr hModule = GetModuleHandle(moduleName);
+            if (hModule == IntPtr.Zero) {
+                System.Diagnostics.Debug.Assert(hModule != IntPtr.Zero, "GetModuleHandle failed.  Dll isn't loaded?");
+                return false;
+            }
+            IntPtr functionPointer = GetProcAddress(hModule, methodName);
+            return (functionPointer != IntPtr.Zero);       
+        }
+        
+        // On CoreCLR this is not the way to determine if a process is a tailored application (which means APPX).
+        // On CoreCLR AppX is determined by a flag past to the host which is exposed by AppDomain.IsAppXProcess in mscorlib.
+        // The reason for this if-def is to ensure nobody takes a dependency on this on CoreCLR.        
+        [System.Security.SecuritySafeCritical]
         private static bool _IsTailoredApplication()
         {
-            if (OSEnvironmentHelper.IsAtLeast(OSVersion.Win8))
+            Version windows8Version = new Version(6, 2, 0, 0);
+            OperatingSystem os = Environment.OSVersion;
+            bool osSupportsPackagedProcesses = os.Platform == PlatformID.Win32NT && os.Version >= windows8Version;
+
+            if (osSupportsPackagedProcesses && DoesWin32MethodExist(KERNEL32, "AppPolicyGetClrCompat"))
             {
-                int bufLen = 0;
-                // Will return ERROR_INSUFFICIENT_BUFFER when running within a tailored application,
+                // Use AppPolicyGetClrCompat if it is available. Return true if and only if this is a UWA which means if
+                // this is packaged desktop app this method will return false. This may cause some confusion however 
+                // this is necessary to make the behavior of packaged desktop apps identical to desktop apps.
+                AppPolicyClrCompat appPolicyClrCompat;
+                return _AppPolicyGetClrCompat(GetCurrentProcessToken(), out appPolicyClrCompat) == ERROR_SUCCESS && 
+                    appPolicyClrCompat == AppPolicyClrCompat.AppPolicyClrCompat_Universal;
+            }
+            else if(osSupportsPackagedProcesses && DoesWin32MethodExist(KERNEL32, "GetCurrentPackageId"))
+            {
+                Int32 bufLen = 0;
+                // Will return ERROR_INSUFFICIENT_BUFFER when running within a packaged application,
                 // and will return ERROR_NO_PACKAGE_IDENTITY otherwise.
-                return GetCurrentPackageId(ref bufLen, null) == ERROR_INSUFFICIENT_BUFFER;
+                return _GetCurrentPackageId(ref bufLen, null) == ERROR_INSUFFICIENT_BUFFER;
             }
             else
-            {
+            {   // We must be running on a downlevel OS.
                 return false;
             }
         }
index 928d9be8f3e48f23a523cc37d815d6ef82bd6967..b99db25d123f6df476c8487733451cd286ba26cf 100644 (file)
@@ -6,6 +6,7 @@ namespace System.ServiceModel.Channels
 {
     using System;
     using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.Linq;
     using System.Net;
@@ -44,6 +45,7 @@ namespace System.ServiceModel.Channels
         static readonly HashSet<char> InvalidSeparatorSet = new HashSet<char>(new char[] { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ' });
         static string currentWebSocketVersion;
 
+        [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:DoNotUseSHA1", Justification = "Cannot change. Usage of SHA1 is part of WebSocket spec. Justification in RFC6455 section 10.8")]
         internal static string ComputeAcceptHeader(string webSocketKey)
         {
             Fx.Assert(webSocketKey != null, "webSocketKey should not be null.");
index 35c78297859f7342bb6f1137a045ea1bf79b932c..a457268b0cec838769a3f3a1db5bc2d6a67d31c1 100644 (file)
@@ -3472,7 +3472,7 @@ namespace System.ServiceModel.Configuration
                 {
                     ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();
                     properties.Add(new ConfigurationProperty("requireClientCertificate", typeof(System.Boolean), false, null, null, System.Configuration.ConfigurationPropertyOptions.None));
-                    properties.Add(new ConfigurationProperty("sslProtocols", typeof(System.Security.Authentication.SslProtocols), System.Security.Authentication.SslProtocols.Ssl3 | System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Default | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12, null, new System.ServiceModel.Configuration.ServiceModelEnumValidator(typeof(System.ServiceModel.Security.SslProtocolsHelper)), System.Configuration.ConfigurationPropertyOptions.None));
+                    properties.Add(new ConfigurationProperty("sslProtocols", typeof(System.Security.Authentication.SslProtocols), System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12, null, new System.ServiceModel.Configuration.ServiceModelEnumValidator(typeof(System.ServiceModel.Security.SslProtocolsHelper)), System.Configuration.ConfigurationPropertyOptions.None));
                     this.properties = properties;
                 }
                 return this.properties;
@@ -3527,7 +3527,7 @@ namespace System.ServiceModel.Configuration
                     properties.Add(new ConfigurationProperty("clientCredentialType", typeof(System.ServiceModel.TcpClientCredentialType), System.ServiceModel.TcpClientCredentialType.Windows, null, new System.ServiceModel.Configuration.ServiceModelEnumValidator(typeof(System.ServiceModel.TcpClientCredentialTypeHelper)), System.Configuration.ConfigurationPropertyOptions.None));
                     properties.Add(new ConfigurationProperty("protectionLevel", typeof(System.Net.Security.ProtectionLevel), System.Net.Security.ProtectionLevel.EncryptAndSign, null, new System.ServiceModel.Configuration.ServiceModelEnumValidator(typeof(System.ServiceModel.Security.ProtectionLevelHelper)), System.Configuration.ConfigurationPropertyOptions.None));
                     properties.Add(new ConfigurationProperty("extendedProtectionPolicy", typeof(System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement), null, null, null, System.Configuration.ConfigurationPropertyOptions.None));
-                    properties.Add(new ConfigurationProperty("sslProtocols", typeof(System.Security.Authentication.SslProtocols), System.Security.Authentication.SslProtocols.Ssl3 | System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Default | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12, null, new System.ServiceModel.Configuration.ServiceModelEnumValidator(typeof(System.ServiceModel.Security.SslProtocolsHelper)), System.Configuration.ConfigurationPropertyOptions.None));
+                    properties.Add(new ConfigurationProperty("sslProtocols", typeof(System.Security.Authentication.SslProtocols), System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12, null, new System.ServiceModel.Configuration.ServiceModelEnumValidator(typeof(System.ServiceModel.Security.SslProtocolsHelper)), System.Configuration.ConfigurationPropertyOptions.None));
                     this.properties = properties;
                 }
                 return this.properties;
index dbef91c1275e3c975dd6f80f03a2cf7e4f640507..e4a23bcc00c085c39804adda91f867b2b031dc70 100644 (file)
@@ -1347,31 +1347,38 @@ namespace System.ServiceModel.Description
 
         internal static XmlSchema CreateWsdl()
         {
-            return XmlSchema.Read(new StringReader(wsdl), null);
+            StringReader reader = new StringReader(wsdl);
+            return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
         }
+
         internal static XmlSchema CreateSoap()
         {
-            return XmlSchema.Read(new StringReader(soap), null);
+            StringReader reader = new StringReader(soap);
+            return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
         }
 
         internal static XmlSchema CreateSoapEncoding()
         {
-            return XmlSchema.Read(new StringReader(soapEncoding), null);
+            StringReader reader = new StringReader(soapEncoding);
+            return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
         }
 
         internal static XmlSchema CreateFakeSoapEncoding()
         {
-            return XmlSchema.Read(new StringReader(fakeSoapEncoding), null);
+            StringReader reader = new StringReader(fakeSoapEncoding);
+            return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
         }
 
         internal static XmlSchema CreateFakeXsdSchema()
         {
-            return XmlSchema.Read(new StringReader(fakeXsd), null);
+            StringReader reader = new StringReader(fakeXsd);
+            return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
         }
 
         internal static XmlSchema CreateFakeXmlSchema()
         {
-            return XmlSchema.Read(new StringReader(fakeXmlSchema), null);
+            StringReader reader = new StringReader(fakeXmlSchema);
+            return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
         }
 
         internal static bool IsKnownSchema(string ns)
index c056108dd68dcceda491ac274d90095456a358cc..f8674ce614d1ee546891906235083aca33d737c8 100644 (file)
@@ -5,6 +5,7 @@
 namespace System.ServiceModel.Description
 {
     using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.IO;
     using System.Linq;
@@ -313,6 +314,8 @@ namespace System.ServiceModel.Description
             return newWsdl;
         }
 
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "This is trusted server code from the application only. We should allow the customer add dtd.")]
         private static XmlSchema CloneXsd(XmlSchema originalXsd)
         {
             Fx.Assert(originalXsd != null, "originalXsd must not be null");
@@ -321,7 +324,7 @@ namespace System.ServiceModel.Description
             {
                 originalXsd.Write(memoryStream);
                 memoryStream.Seek(0, SeekOrigin.Begin);
-                newXsd = XmlSchema.Read(memoryStream, null);
+                newXsd = XmlSchema.Read(new XmlTextReader(memoryStream) { DtdProcessing = DtdProcessing.Parse }, null);
             }
 
             return newXsd;
index d34430b8733dc0ad20fd023e56c7e49ab6e2c7cf..c7fb34872177998c56ac4635e18eefff6a0eb28a 100644 (file)
@@ -7,6 +7,7 @@ namespace System.ServiceModel.Dispatcher
     using System.Collections;
     using System.Collections.Generic;
     using System.Collections.ObjectModel;
+    using System.Diagnostics.CodeAnalysis;
     using System.Runtime;
     using System.ServiceModel.Channels;
     using System.ServiceModel.Diagnostics;
@@ -262,6 +263,7 @@ namespace System.ServiceModel.Dispatcher
             }
         }
 
+        [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml")]
         static QueryMatcher()
         {
             QueryMatcher.defaultFunctionLibs = new IFunctionLibrary[] { new XPathFunctionLibrary() };
index 9bf6328b8221647e9591c0b9b76000bdb08c8cf6..2b9ff6aeda7890d4856a7ad26e7213ff83d6b86c 100644 (file)
@@ -8,12 +8,11 @@ namespace System.ServiceModel.Dispatcher
     using System.Diagnostics;
     using System.Reflection;
     using System.Runtime;
-    using System.Runtime.Diagnostics;
     using System.Security;
     using System.ServiceModel.Description;
     using System.ServiceModel.Diagnostics;
-    using System.ServiceModel.Diagnostics.Application;
     using System.Threading.Tasks;
+    using Threading;
 
     /// <summary>
     /// An invoker used when some operation contract has a return value of Task or its generic counterpart (Task of T) 
@@ -21,14 +20,12 @@ namespace System.ServiceModel.Dispatcher
     internal class TaskMethodInvoker : IOperationInvoker
     {
         private const string ResultMethodName = "Result";
-        private MethodInfo taskMethod;
-        private bool isGenericTask;
+        private readonly MethodInfo taskMethod;
         private InvokeDelegate invokeDelegate;
         private int inputParameterCount;
         private int outputParameterCount;
-        private object[] outputs;
-        private MethodInfo toAsyncMethodInfo;
         private MethodInfo taskTResultGetMethod;
+        private bool isGenericTask;
 
         public TaskMethodInvoker(MethodInfo taskMethod, Type taskType)
         {
@@ -41,7 +38,6 @@ namespace System.ServiceModel.Dispatcher
 
             if (taskType != ServiceReflector.VoidType)
             {
-                this.toAsyncMethodInfo = TaskExtensions.MakeGenericMethod(taskType);
                 this.taskTResultGetMethod = ((PropertyInfo)taskMethod.ReturnType.GetMember(ResultMethodName)[0]).GetGetMethod();
                 this.isGenericTask = true;
             }
@@ -57,36 +53,11 @@ namespace System.ServiceModel.Dispatcher
             get { return this.taskMethod; }
         }
 
-        private InvokeDelegate InvokeDelegate
-        {
-            get
-            {
-                this.EnsureIsInitialized();
-                return this.invokeDelegate;
-            }
-        }
-
-        private int InputParameterCount
-        {
-            get
-            {
-                this.EnsureIsInitialized();
-                return this.inputParameterCount;
-            }
-        }
-
-        private int OutputParameterCount
-        {
-            get
-            {
-                this.EnsureIsInitialized();
-                return this.outputParameterCount;
-            }
-        }
-
         public object[] AllocateInputs()
         {
-            return EmptyArray.Allocate(this.InputParameterCount);
+            EnsureIsInitialized();
+
+            return EmptyArray<object>.Allocate(this.inputParameterCount);
         }
 
         public object Invoke(object instance, object[] inputs, out object[] outputs)
@@ -95,169 +66,249 @@ namespace System.ServiceModel.Dispatcher
         }
 
         public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
+        {
+            return ToApm(InvokeAsync(instance, inputs), callback, state);
+        }
+
+        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
         {
             if (instance == null)
             {
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject)));
             }
 
-            if (inputs == null)
-            {
-                if (this.InputParameterCount > 0)
-                {
-                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.InputParameterCount)));
-                }
-            }
-            else if (inputs.Length != this.InputParameterCount)
-            {
-                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.InputParameterCount, inputs.Length)));
-            }
-
-            this.outputs = EmptyArray.Allocate(this.OutputParameterCount);
-
-            AsyncMethodInvoker.StartOperationInvokePerformanceCounters(this.taskMethod.Name);
-
-            IAsyncResult returnValue;
+            object returnVal = null;
             bool callFailed = true;
             bool callFaulted = false;
             ServiceModelActivity activity = null;
+            Activity boundOperation = null;
 
             try
             {
-                Activity boundActivity = null;
-                AsyncMethodInvoker.CreateActivityInfo(ref activity, ref boundActivity);
+                AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation);
 
-                AsyncMethodInvoker.StartOperationInvokeTrace(this.taskMethod.Name);
-                                
-                using (boundActivity)
+                Task<Tuple<object, object[]>> invokeTask = result as Task<Tuple<object, object[]>>;
+
+                if (invokeTask == null)
                 {
-                    if (DiagnosticUtility.ShouldUseActivity)
+                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.SFxInvalidCallbackIAsyncResult));
+                }
+
+                AggregateException ae = null;
+                Tuple<object, object[]> tuple = null;
+                Task task = null;
+
+                if (invokeTask.IsFaulted)
+                {
+                    Fx.Assert(invokeTask.Exception != null, "Task.IsFaulted guarantees non-null exception.");
+                    ae = invokeTask.Exception;
+                }
+                else
+                {
+                    Fx.Assert(invokeTask.IsCompleted, "Task.Result is expected to be completed");
+
+                    tuple = invokeTask.Result;
+                    task = tuple.Item1 as Task;
+
+                    if (task == null)
                     {
-                        string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name);
-                        ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode);
+                        outputs = tuple.Item2;
+                        return null;
                     }
 
-                    object taskReturnValue = this.InvokeDelegate(instance, inputs, this.outputs);
-
-                    if (taskReturnValue == null)
+                    if (task.IsFaulted)
                     {
-                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task");
+                        Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception.");
+                        ae = task.Exception;
                     }
-                    else if (this.isGenericTask)
+                }
+
+                if (ae != null && ae.InnerException != null)
+                {
+                    if (ae.InnerException is FaultException)
                     {
-                        returnValue = (IAsyncResult)this.toAsyncMethodInfo.Invoke(null, new object[] { taskReturnValue, callback, state });
+                        // If invokeTask.IsFaulted we produce the 'callFaulted' behavior below.
+                        // Any other exception will retain 'callFailed' behavior.
+                        callFaulted = true;
+                        callFailed = false;
                     }
-                    else
+
+                    if (ae.InnerException is SecurityException)
                     {
-                        returnValue = ((Task)taskReturnValue).AsAsyncResult(callback, state);
+                        DiagnosticUtility.TraceHandledException(ae.InnerException, TraceEventType.Warning);
+                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException());
                     }
 
-                    callFailed = false;
+                    invokeTask.GetAwaiter().GetResult();
                 }
-            }
-            catch (System.Security.SecurityException e)
-            {
-                DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
-                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException());
-            }
-            catch (Exception e)
-            {
-                TraceUtility.TraceUserCodeException(e, this.taskMethod);
-                if (e is FaultException)
+
+                // Task cancellation without an exception indicates failure but we have no
+                // additional information to provide.  Accessing Task.Result will throw a
+                // TaskCanceledException.   For consistency between void Tasks and Task<T>,
+                // we detect and throw here.
+                if (task.IsCanceled)
                 {
-                    callFaulted = true;
-                    callFailed = false;
+                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TaskCanceledException(task));
                 }
 
-                throw;
+                outputs = tuple.Item2;
+
+                returnVal = this.isGenericTask ? this.taskTResultGetMethod.Invoke(task, Type.EmptyTypes) : null;
+                callFailed = false;
+
+                return returnVal;
             }
             finally
             {
-                ServiceModelActivity.Stop(activity);
-
-                // Any exception above means InvokeEnd will not be called, so complete it here.
-                if (callFailed || callFaulted)
+                if (boundOperation != null)
                 {
-                    AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name);
-                    AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name);
+                    ((IDisposable)boundOperation).Dispose();
                 }
-            }
 
-            return returnValue;
+                ServiceModelActivity.Stop(activity);
+                AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name);
+                AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name);
+            }
         }
 
-        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
+        private async Task<Tuple<object, object[]>> InvokeAsync(object instance, object[] inputs)
         {
-            object returnVal;
-            bool callFailed = true;
-            bool callFaulted = false;
-            ServiceModelActivity activity = null;
+            EnsureIsInitialized();
 
             if (instance == null)
             {
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject)));
             }
 
+            if (inputs == null)
+            {
+                if (this.inputParameterCount > 0)
+                {
+                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.inputParameterCount)));
+                }
+            }
+            else if (inputs.Length != this.inputParameterCount)
+            {
+                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.inputParameterCount, inputs.Length)));
+            }
+
+            object[] outputs = EmptyArray.Allocate(this.outputParameterCount);
+
+            AsyncMethodInvoker.StartOperationInvokePerformanceCounters(this.taskMethod.Name);
+
+            object returnValue;
+            ServiceModelActivity activity = null;
+            Activity boundActivity = null;
+
             try
             {
-                Activity boundOperation = null;
-                AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation);
+                AsyncMethodInvoker.CreateActivityInfo(ref activity, ref boundActivity);
+                AsyncMethodInvoker.StartOperationInvokeTrace(this.taskMethod.Name);
 
-                using (boundOperation)
+                if (DiagnosticUtility.ShouldUseActivity)
                 {
-                    Task task = result as Task;
+                    string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name);
+                    ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode);
+                }
 
-                    Fx.Assert(task != null, "InvokeEnd needs to be called with the result returned from InvokeBegin.");
-                    if (task.IsFaulted)
-                    {
-                        Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception.");
+                OperationContext.EnableAsyncFlow();
 
-                        // If FaultException is thrown, we will get 'callFaulted' behavior below.
-                        // Any other exception will retain 'callFailed' behavior.
-                        throw FxTrace.Exception.AsError<FaultException>(task.Exception);
-                    }
+                returnValue = this.invokeDelegate(instance, inputs, outputs);
 
-                    // Task cancellation without an exception indicates failure but we have no
-                    // additional information to provide.  Accessing Task.Result will throw a
-                    // TaskCanceledException.   For consistency between void Tasks and Task<T>,
-                    // we detect and throw here.
-                    if (task.IsCanceled)
-                    {
-                        throw FxTrace.Exception.AsError(new TaskCanceledException(task));
-                    }
+                if (returnValue == null)
+                {
+                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task");
+                }
 
-                    outputs = this.outputs;
-                    if (this.isGenericTask)
-                    {
-                        returnVal = this.taskTResultGetMethod.Invoke(result, Type.EmptyTypes);
-                    }
-                    else
-                    {                        
-                        returnVal = null;
-                    }
+                var returnValueTask = returnValue as Task;
 
-                    callFailed = false;
+                if (returnValueTask != null)
+                {
+                    // Only return once the task has completed                        
+                    await returnValueTask;
                 }
+
+                return Tuple.Create(returnValue, outputs);
             }
             catch (SecurityException e)
             {
                 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException());
             }
-            catch (FaultException)
+            catch (Exception e)
             {
-                callFaulted = true;
-                callFailed = false;
+                TraceUtility.TraceUserCodeException(e, this.taskMethod);
                 throw;
             }
             finally
             {
+                OperationContext.DisableAsyncFlow();
+
+                if (boundActivity != null)
+                {
+                    ((IDisposable)boundActivity).Dispose();
+                }
+
                 ServiceModelActivity.Stop(activity);
-                AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name);
-                AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name);
             }
+        }
+
+        // Helper method when implementing an APM wrapper around a Task based async method which returns a result. 
+        // In the BeginMethod method, you would call use ToApm to wrap a call to MethodAsync:
+        //     return MethodAsync(params).ToApm(callback, state);
+        // In the EndMethod, you would use ToApmEnd<TResult> to ensure the correct exception handling
+        // This will handle throwing exceptions in the correct place and ensure the IAsyncResult contains the provided
+        // state object
+        private static Task<TResult> ToApm<TResult>(Task<TResult> task, AsyncCallback callback, object state)
+        {
+            // When using APM, the returned IAsyncResult must have the passed in state object stored in AsyncState. This
+            // is so the callback can regain state. If the incoming task already holds the state object, there's no need
+            // to create a TaskCompletionSource to ensure the returned (IAsyncResult)Task has the right state object.
+            // This is a performance optimization for this special case.
+            if (task.AsyncState == state)
+            {
+                if (callback != null)
+                {
+                    task.ContinueWith((antecedent, obj) =>
+                    {
+                        AsyncCallback callbackObj = (AsyncCallback)obj;
+                        callbackObj(antecedent);
+                    }, callback, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default);
+                }
+
+                return task;
+            }
+
+            // Need to create a TaskCompletionSource so that the returned Task object has the correct AsyncState value.
+            var tcs = new TaskCompletionSource<TResult>(state);
+            var continuationState = Tuple.Create(tcs, callback);
+
+            task.ContinueWith((antecedent, obj) =>
+            {
+                Tuple<TaskCompletionSource<TResult>, AsyncCallback> tuple = (Tuple<TaskCompletionSource<TResult>, AsyncCallback>)obj;
+                TaskCompletionSource<TResult> tcsObj = tuple.Item1;
+                AsyncCallback callbackObj = tuple.Item2;
+
+                if (antecedent.IsFaulted)
+                {
+                    tcsObj.TrySetException(antecedent.Exception.InnerException);
+                }
+                else if (antecedent.IsCanceled)
+                {
+                    tcsObj.TrySetCanceled();
+                }
+                else
+                {
+                    tcsObj.TrySetResult(antecedent.Result);
+                }
+
+                if (callbackObj != null)
+                {
+                    callbackObj(tcsObj.Task);
+                }
+            }, continuationState, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default);
 
-            return returnVal;
+            return tcs.Task;
         }
 
         private void EnsureIsInitialized()
index 5d826dfb4895a9caa6b64a1f538818f4f54a7069..0072f122b8af667fcb0971d7731ca3cc5048df00 100644 (file)
@@ -92,7 +92,7 @@ namespace System.ServiceModel.Dispatcher
                     bufferWriter.Flush();
                     XmlDocument doc = new XmlDocument();
                     memoryStream.Position = 0;
-                    doc.Load(memoryStream);
+                    doc.Load(new XmlTextReader(memoryStream) { DtdProcessing = DtdProcessing.Prohibit });
                     //doc.Save(Console.Out);
                     foreach (XmlElement element in doc.DocumentElement.ChildNodes)
                     {
index dd5b3ef3436642510c6a8dc6a0e720bfccc40845..d7e24e00a8ea3418cc4ea24d732908a645455d20 100644 (file)
@@ -67,7 +67,7 @@ namespace System.ServiceModel
 
         static XmlSchema GetEprSchema()
         {
-            using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema)))
+            using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema)) { DtdProcessing = DtdProcessing.Prohibit })
             {
                 return XmlSchema.Read(reader, null);
             }
index b60cc2b287a5d1b83f1afdb0f16b46e2f35973ec..d74bdeb89cc108c97fc13db7c3f9ecb66c128b95 100644 (file)
@@ -67,7 +67,7 @@ namespace System.ServiceModel
 
         static XmlSchema GetEprSchema()
         {
-            using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema)))
+            using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema)) { DtdProcessing = DtdProcessing.Prohibit })
             {
                 return XmlSchema.Read(reader, null);
             }
index 616b1feddc328529b05842dd31a3e7594928eae3..323304ff6ba3fca8dbf43101c111d4375de7adda 100644 (file)
@@ -14,9 +14,11 @@ namespace System.ServiceModel
     {
         private const string DisableExplicitConnectionCloseHeaderString = "Switch.System.ServiceModel.DisableExplicitConnectionCloseHeader";
         private const string AllowUnsignedToHeaderString = "Switch.System.ServiceModel.AllowUnsignedToHeader";
+        private const string DisableCngCertificatesString = "Switch.System.ServiceModel.DisableCngCertificates";
 
         private static int disableExplicitConnectionCloseHeader;
         private static int allowUnsignedToHeader;
+        private static int disableCngCertificates;
 
         public static bool DisableExplicitConnectionCloseHeader
         {
@@ -36,10 +38,29 @@ namespace System.ServiceModel
             }
         }
 
+        public static bool DisableCngCertificates
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return LocalAppContext.GetCachedSwitchValue(DisableCngCertificatesString, ref disableCngCertificates);
+            }
+        }
+
         public static void SetDefaultsLessOrEqual_452()
         {
+#pragma warning disable BCL0012            
             // Define the switches that should be true for 4.5.2 or less, false for 4.6+.
             LocalAppContext.DefineSwitchDefault(DisableExplicitConnectionCloseHeaderString, true);
+#pragma warning restore BCL0012
+        }
+
+        public static void SetDefaultsLessOrEqual_461()
+        {
+#pragma warning disable BCL0012            
+            // Define the switches that should be true for 4.6.1 or less, false for 4.6.2+.
+            LocalAppContext.DefineSwitchDefault(DisableCngCertificatesString, true);
+#pragma warning restore BCL0012
         }
     }
 }
index 08794986728b577877e5bdebd9b8f624b9d1de3a..c08a1200cb8a269d4cd1e4b9173df09770ae5b4e 100644 (file)
@@ -5,19 +5,21 @@
 namespace System.ServiceModel
 {
     using System.Collections.Generic;
-    using System.ComponentModel;
     using System.Runtime;
     using System.Security.Claims;
     using System.Security.Principal;
     using System.ServiceModel.Channels;
     using System.ServiceModel.Dispatcher;
     using System.ServiceModel.Security;
+    using System.Threading;
 
     public sealed class OperationContext : IExtensibleObject<OperationContext>
     {
         [ThreadStatic]
         static Holder currentContext;
 
+        static AsyncLocal<OperationContext> currentAsyncLocalContext = new AsyncLocal<OperationContext>();
+
         ServiceChannel channel;
         Message clientReply;
         bool closeClientReply;
@@ -33,6 +35,7 @@ namespace System.ServiceModel
         MessageHeaders outgoingMessageHeaders;
         MessageVersion outgoingMessageVersion;
         EndpointDispatcher endpointDispatcher;
+        bool isAsyncFlowEnabled;
 
         public event EventHandler OperationCompleted;
 
@@ -92,12 +95,19 @@ namespace System.ServiceModel
         {
             get
             {
-                return CurrentHolder.Context;
+                return ShouldUseAsyncLocalContext ? OperationContext.currentAsyncLocalContext.Value : CurrentHolder.Context;
             }
 
             set
             {
-                CurrentHolder.Context = value;
+                if (ShouldUseAsyncLocalContext)
+                {
+                    OperationContext.currentAsyncLocalContext.Value = value;
+                }
+                else
+                {
+                    CurrentHolder.Context = value;
+                }                
             }
         }
 
@@ -115,6 +125,14 @@ namespace System.ServiceModel
             }
         }
 
+        private static bool ShouldUseAsyncLocalContext
+        {
+            get
+            {
+                return CurrentHolder.Context == null && OperationContext.currentAsyncLocalContext.Value != null && OperationContext.currentAsyncLocalContext.Value.isAsyncFlowEnabled;
+            }
+        }
+
         public EndpointDispatcher EndpointDispatcher
         {
             get
@@ -339,6 +357,21 @@ namespace System.ServiceModel
             this.clientReply = null;
         }
 
+        internal static void EnableAsyncFlow()
+        {
+            CurrentHolder.Context.isAsyncFlowEnabled = true;
+            currentAsyncLocalContext.Value = CurrentHolder.Context;
+        }
+
+        internal static void DisableAsyncFlow()
+        {
+            if (OperationContext.Current != null && OperationContext.Current.isAsyncFlowEnabled)
+            {
+                OperationContext.Current.isAsyncFlowEnabled = false;
+                currentAsyncLocalContext.Value = null;
+            }
+        }
+
         internal void FireOperationCompleted()
         {
             try
index 17da631e14969af50e6f5479cf9ca756209e06f4..3d12f54c8641bde9b154c8ac8c718f2b0b6d3bdb 100644 (file)
@@ -10,14 +10,12 @@ namespace System.ServiceModel
 
     public sealed class OperationContextScope : IDisposable
     {
-        [ThreadStatic]
-        static OperationContextScope currentScope;
+        static AsyncLocal<OperationContextScope> currentScope = new AsyncLocal<OperationContextScope>();
 
         OperationContext currentContext;
         bool disposed;
         readonly OperationContext originalContext = OperationContext.Current;
-        readonly OperationContextScope originalScope = OperationContextScope.currentScope;
-        readonly Thread thread = Thread.CurrentThread;
+        readonly OperationContextScope originalScope = OperationContextScope.currentScope.Value;
 
         public OperationContextScope(IContextChannel channel)
         {
@@ -41,22 +39,19 @@ namespace System.ServiceModel
         void PushContext(OperationContext context)
         {
             this.currentContext = context;
-            OperationContextScope.currentScope = this;
+            OperationContextScope.currentScope.Value = this;
             OperationContext.Current = this.currentContext;
         }
 
         void PopContext()
         {
-            if (this.thread != Thread.CurrentThread)
-                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidContextScopeThread0)));
-
-            if (OperationContextScope.currentScope != this)
+            if (OperationContextScope.currentScope.Value != this)
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInterleavedContextScopes0)));
 
             if (OperationContext.Current != this.currentContext)
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxContextModifiedInsideScope0)));
 
-            OperationContextScope.currentScope = this.originalScope;
+            OperationContextScope.currentScope.Value = this.originalScope;
             OperationContext.Current = this.originalContext;
 
             if (this.currentContext != null)
index ff0d508ecb02211e914a2e14ced66a26e543155c..7c0b7a8cb2e0e114d729fcd25d15d1a1e0b200ca 100644 (file)
@@ -17,6 +17,7 @@ namespace System.ServiceModel.Security
     using System.Text;
     using System.Xml;
     using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
     using System.Security.Cryptography;
 
     using Psha1DerivedKeyGenerator = System.IdentityModel.Psha1DerivedKeyGenerator;
@@ -57,6 +58,7 @@ namespace System.ServiceModel.Security
             return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha256Digest);
         }
 
+        [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:DoNotUseSHA1", Justification = "Cannot change. Required as SOAP spec requires supporting SHA1.")]
         internal static HashAlgorithm CreateHashAlgorithm(string digestMethod)
         {
             object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(digestMethod);
@@ -86,6 +88,7 @@ namespace System.ServiceModel.Security
             }
         }
 
+        [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:DoNotUseSHA1", Justification = "Cannot change. Required as SOAP spec requires supporting SHA1.")]
         internal static HashAlgorithm CreateHashForAsymmetricSignature(string signatureMethod)
         {
             object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(signatureMethod);
index 913840d0359797a0ae39e848365a43eb6eb550bf..b62aceefcff29d0061ab33c65db191ab5faee7c8 100644 (file)
@@ -899,8 +899,45 @@ namespace System.ServiceModel.Security
         [SecuritySafeCritical]
         static bool CanKeyDoKeyExchange(X509Certificate2 certificate)
         {
-            CspKeyContainerInfo info = GetKeyContainerInfo(certificate);
-            return info != null && info.KeyNumber == KeyNumber.Exchange;
+            bool canDoKeyExchange = false;
+
+            if (!LocalAppContextSwitches.DisableCngCertificates)
+            {
+                X509KeyUsageExtension keyUsageExtension = null;
+                for (int i = 0; i < certificate.Extensions.Count; i++)
+                {
+                    keyUsageExtension = certificate.Extensions[i] as X509KeyUsageExtension;
+                    if (keyUsageExtension != null)
+                    {
+                        break;
+                    }
+                }
+
+                // No KeyUsage extension means most usages are permitted including key exchange.
+                // See RFC 5280 section 4.2.1.3 (Key Usage) for details. If the extension is non-critical
+                // then it's non-enforcing and meant as an aid in choosing the best certificate when
+                // there are multiple certificates to choose from. 
+                if (keyUsageExtension == null || !keyUsageExtension.Critical)
+                {
+                    return true;
+                }
+
+                // One of KeyAgreement, KeyEncipherment or DigitalSignature need to be allowed depending on the cipher
+                // being used. See RFC 5246 section 7.4.6 for more details.
+                // Additionally, according to msdn docs for PFXImportCertStore, the key specification is set to AT_KEYEXCHANGE
+                // when the data encipherment usage is set.
+                canDoKeyExchange = (keyUsageExtension.KeyUsages &
+                    (X509KeyUsageFlags.KeyAgreement | X509KeyUsageFlags.KeyEncipherment |
+                     X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.DataEncipherment)) != X509KeyUsageFlags.None;
+            }
+
+            if (!canDoKeyExchange)
+            {
+                CspKeyContainerInfo info = GetKeyContainerInfo(certificate);
+                canDoKeyExchange = info != null && info.KeyNumber == KeyNumber.Exchange;
+            }
+
+            return canDoKeyExchange;
         }
 
         [Fx.Tag.SecurityNote(Critical = "Elevates to call properties: X509Certificate2.PrivateKey and CspKeyContainerInfo. Caller must protect the return value.")]
@@ -1866,6 +1903,52 @@ namespace System.ServiceModel.Security
             }
         }
 
+        public static bool CanReadPrivateKey(X509Certificate2 certificate)
+        {
+            if (!certificate.HasPrivateKey)
+                return false;
+
+            try
+            {
+                // CNG key, CNG permissions tests
+                using (RSA rsa = CngLightup.GetRSAPrivateKey(certificate))
+                {
+                    if (rsa != null)
+                    {
+                        return true;
+                    }
+                }
+
+                using (DSA dsa = CngLightup.GetDSAPrivateKey(certificate))
+                {
+                    if (dsa != null)
+                    {
+                        return true;
+                    }
+                }
+
+                using (ECDsa ecdsa = CngLightup.GetECDsaPrivateKey(certificate))
+                {
+                    if (ecdsa != null)
+                    {
+                        return true;
+                    }
+                }
+
+                // CAPI key, CAPI permissions test
+                if (certificate.PrivateKey != null)
+                {
+                    return true;
+                }
+
+                return false;
+            }
+            catch (CryptographicException)
+            {
+                return false;
+            }
+        }
+
         static class NetworkCredentialHelper
         {
             [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical methods UnsafeGetUsername, UnsafeGetPassword, and UnsafeGetDomain to access the credential details without a Demand.",
index 0032edc9ea8587e863b8bb5741abf6b7f5304b4b..597228934389296fc09a746791dc777f463925cf 100644 (file)
@@ -543,7 +543,14 @@ namespace System.ServiceModel.Security
             bool hasPrivateKey = false;
             try
             {
-                hasPrivateKey = certificate != null && certificate.PrivateKey != null;
+                if (System.ServiceModel.LocalAppContextSwitches.DisableCngCertificates)
+                {
+                    hasPrivateKey = certificate != null && certificate.PrivateKey != null;
+                }
+                else
+                {
+                    hasPrivateKey = certificate.HasPrivateKey && SecurityUtils.CanReadPrivateKey(certificate);
+                }
             }
             catch (SecurityException e)
             {
index b9f10c42f55ebf54486b9b584b9227d57e0f086a..5641522d6ed32f497fe110e7a66e70b26cbe73f5 100644 (file)
@@ -461,7 +461,7 @@ namespace System.ServiceModel.Security.Tokens
 
             XmlDocument dom = new XmlDocument();
             dom.PreserveWhitespace = true;
-            dom.Load(stream);
+            dom.Load(new XmlTextReader(stream) { DtdProcessing = DtdProcessing.Prohibit });
             stream.Close();
 
             return dom.DocumentElement;
index e3d7cf18cc07d587f1e980a4e513774963b751e3..417886dd3eba68ef6d147d84828ba4cd1efa0ae1 100644 (file)
@@ -2310,7 +2310,7 @@ namespace System.ServiceModel.Security
                 writer.WriteEndElement();
                 writer.Flush();
                 stream.Seek(0, SeekOrigin.Begin);
-                result = (XmlElement)doc.ReadNode(new XmlTextReader(stream));
+                result = (XmlElement)doc.ReadNode(new XmlTextReader(stream) { DtdProcessing = DtdProcessing.Prohibit });
             }
             return result;
         }
index 2795cd2b3eca8eea7464ea48b07a0e36cf34ae32..2b65cc9326e2bbcd9574d9563373bab1921085bb 100644 (file)
@@ -1417,7 +1417,7 @@ namespace System.ServiceModel.Security
                     writer.Flush();
                     stream.Seek(0, SeekOrigin.Begin);
                     XmlNode skiNode;
-                    using (XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(new XmlTextReader(stream)))
+                    using (XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(new XmlTextReader(stream) { DtdProcessing = DtdProcessing.Prohibit }))
                     {
                         reader.MoveToContent();
                         skiNode = doc.ReadNode(reader);
index 81df58a3069e5ff171d11fed73dc25d5fab47202..1bd584b2806af9a18b3a131b41a8151545fe09e1 100644 (file)
@@ -2064,7 +2064,8 @@ namespace System.ServiceModel.Security
                     throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID5004, ns));
             }
 
-            return XmlSchema.Read(new StringReader(xmlSchema), null);
+            StringReader reader = new StringReader(xmlSchema);
+            return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
         }
 
         /// <summary>
index 47a80aaf77243b741f856953711713b6f8963e66..37ca8e48b951c8f1a1eecc1960c5e06849b6fba0 100644 (file)
@@ -1,4 +1,4 @@
- //-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // Copyright (c) Microsoft Corporation.  All rights reserved.
 //-----------------------------------------------------------------------------
 
@@ -1076,6 +1076,9 @@ namespace System.ServiceModel
                 {
                     ManagementExtension.OnServiceOpened(this);
                 }
+
+                // log telemetry data for the current WCF service.
+                TelemetryTraceLogging.LogSeriveKPIData(this.Description);
             }
             base.OnOpened();
 
index b7c7db2a426e186689f57b5cb1bfb1ea1d2ce26d..19fba5c99a817ccc5faa6fddf9da398470c4d950 100644 (file)
@@ -15,12 +15,15 @@ namespace System.ServiceModel
         internal const string HttpTransportPerFactoryConnectionPoolString = "wcf:httpTransportBinding:useUniqueConnectionPoolPerFactory";
         internal const string EnsureUniquePerformanceCounterInstanceNamesString = "wcf:ensureUniquePerformanceCounterInstanceNames";
         internal const string UseConfiguredTransportSecurityHeaderLayoutString = "wcf:useConfiguredTransportSecurityHeaderLayout";
+        internal const string UseBestMatchNamedPipeUriString = "wcf:useBestMatchNamedPipeUri";
         const bool DefaultHttpTransportPerFactoryConnectionPool = false;
         const bool DefaultEnsureUniquePerformanceCounterInstanceNames = false;
         const bool DefaultUseConfiguredTransportSecurityHeaderLayout = false;
+        const bool DefaultUseBestMatchNamedPipeUri = false;
         static bool httpTransportPerFactoryConnectionPool;
         static bool ensureUniquePerformanceCounterInstanceNames;
         static bool useConfiguredTransportSecurityHeaderLayout;
+        static bool useBestMatchNamedPipeUri;
         static volatile bool settingsInitalized = false;
         static object appSettingsLock = new object();
 
@@ -54,6 +57,16 @@ namespace System.ServiceModel
             }
         }
 
+        internal static bool UseBestMatchNamedPipeUri
+        {
+            get
+            {
+                EnsureSettingsLoaded();
+
+                return useBestMatchNamedPipeUri;
+            }
+        }
+
         [SuppressMessage(FxCop.Category.ReliabilityBasic, "Reliability104:CaughtAndHandledExceptionsRule",
             Justification = "Handle the configuration exceptions here to avoid regressions on customer's existing scenarios")]
         static void EnsureSettingsLoaded()
@@ -89,6 +102,11 @@ namespace System.ServiceModel
                                 useConfiguredTransportSecurityHeaderLayout = DefaultUseConfiguredTransportSecurityHeaderLayout;
                             }
 
+                            if ((appSettingsSection == null) || !bool.TryParse(appSettingsSection[UseBestMatchNamedPipeUriString], out useBestMatchNamedPipeUri))
+                            {
+                                useBestMatchNamedPipeUri = DefaultUseBestMatchNamedPipeUri;
+                            }
+
                             settingsInitalized = true;
                         }
                     }
index 969772454c5434dc9ee4a2b961b9b0d9bc222dca..a62d82e0b93426c99cb53eeb5d11100e38d0c986 100644 (file)
@@ -4,6 +4,7 @@
 
 namespace System
 {
+    using System.Collections.Concurrent;
     using System.Collections.Generic;
     using System.Collections.ObjectModel;
     using System.Collections.Specialized;
@@ -11,6 +12,7 @@ namespace System
     using System.ServiceModel;
     using System.ServiceModel.Channels;
     using System.Text;
+    using System.Threading;
     using System.Runtime.CompilerServices;
     using System.Globalization;
 
@@ -31,7 +33,7 @@ namespace System
         const string NullableDefault = "null";
         readonly WildcardInfo wildcard;
         IDictionary<string, string> defaults;
-        Dictionary<string, string> unescapedDefaults;
+        ConcurrentDictionary<string, string> unescapedDefaults;
 
         VariablesCollection variables;
 
@@ -263,7 +265,7 @@ namespace System
             {
                 if (this.defaults == null)
                 {
-                    this.defaults = new UriTemplateDefaults(this);
+                    Interlocked.CompareExchange<IDictionary<string, string>>(ref this.defaults, new UriTemplateDefaults(this), null);
                 }
                 return this.defaults;
             }
@@ -943,16 +945,10 @@ namespace System
             }
             if (this.unescapedDefaults == null)
             {
-                this.unescapedDefaults = new Dictionary<string, string>(StringComparer.Ordinal);
-            }
-            string unescapedValue;
-            if (!this.unescapedDefaults.TryGetValue(escapedValue, out unescapedValue))
-            {
-                unescapedValue = Uri.UnescapeDataString(escapedValue);
-                this.unescapedDefaults.Add(escapedValue, unescapedValue);
+                this.unescapedDefaults = new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
             }
 
-            return unescapedValue;
+            return this.unescapedDefaults.GetOrAdd(escapedValue, Uri.UnescapeDataString);
         }
 
         struct BindInformation
@@ -1181,8 +1177,8 @@ namespace System
                 {
                     if (this.pathSegmentVariableNamesSnapshot == null)
                     {
-                        this.pathSegmentVariableNamesSnapshot = new ReadOnlyCollection<string>(
-                            this.pathSegmentVariableNames);
+                        Interlocked.CompareExchange<ReadOnlyCollection<string>>(ref this.pathSegmentVariableNamesSnapshot, new ReadOnlyCollection<string>(
+                            this.pathSegmentVariableNames), null);
                     }
                     return this.pathSegmentVariableNamesSnapshot;
                 }
@@ -1193,8 +1189,8 @@ namespace System
                 {
                     if (this.queryValueVariableNamesSnapshot == null)
                     {
-                        this.queryValueVariableNamesSnapshot = new ReadOnlyCollection<string>(
-                            this.queryValueVariableNames);
+                        Interlocked.CompareExchange<ReadOnlyCollection<string>>(ref this.queryValueVariableNamesSnapshot, new ReadOnlyCollection<string>(
+                            this.queryValueVariableNames), null);
                     }
                     return this.queryValueVariableNamesSnapshot;
                 }
index 7e89f129e7c015cb1446ac7e8ef27bebbad77865..51d5a3c922e21e2dd4072863a56bdbf96b230d04 100644 (file)
@@ -11,6 +11,7 @@
     using System.Web.Resources;
     using System.Web.UI;
     using System.Web.UI.WebControls;
+    using System.Web.DynamicData.Util;
 
     /// <summary>
     /// Validator that enforces model validation. It can be used either at the field level or the entity level
                 }
 
                 if (!attrib.IsValid(value)) {
-                    ErrorMessage = HttpUtility.HtmlEncode(attrib.FormatErrorMessage(Column.DisplayName));
+                    ErrorMessage = HttpUtility.HtmlEncode(StringLocalizerUtil.GetLocalizedString(attrib, Column.DisplayName));
                     return false;
                 }
             }
index 33381499ece2f29f0e3aae2a98a9788fd92f0557..324ddf3a0a11f7b067a36424deee60253d97f470 100644 (file)
@@ -516,7 +516,8 @@ namespace System.Web.DynamicData {
             validator.MaximumValue = converter(rangeAttribute.Maximum);
 
             if (String.IsNullOrEmpty(validator.ErrorMessage)) {
-                validator.ErrorMessage = HttpUtility.HtmlEncode(rangeAttribute.FormatErrorMessage(column.DisplayName));
+                validator.ErrorMessage = HttpUtility.HtmlEncode(
+                    StringLocalizerUtil.GetLocalizedString(rangeAttribute, column.DisplayName));
             }
         }
 
@@ -533,7 +534,8 @@ namespace System.Web.DynamicData {
             validator.ValidationExpression = regexAttribute.Pattern;
 
             if (String.IsNullOrEmpty(validator.ErrorMessage)) {
-                validator.ErrorMessage = HttpUtility.HtmlEncode(regexAttribute.FormatErrorMessage(column.DisplayName));
+                validator.ErrorMessage = HttpUtility.HtmlEncode(
+                    StringLocalizerUtil.GetLocalizedString(regexAttribute, column.DisplayName));
             }
         }
 
index 41ce63ba26f8f37451932aa1c727b347c8a9cc0d..74fb8fb0fe7834c8e57ca0e70b8c7a8ec1428afe 100644 (file)
@@ -250,7 +250,8 @@ namespace System.Web.DynamicData {
         public string RequiredErrorMessage {
             get {
                 var requiredAttribute = Metadata.RequiredAttribute;
-                return requiredAttribute != null ? requiredAttribute.FormatErrorMessage(DisplayName) : String.Empty;
+                return requiredAttribute != null ? 
+                    StringLocalizerUtil.GetLocalizedString(requiredAttribute, DisplayName) : String.Empty;
             }
         }
 
@@ -590,7 +591,7 @@ namespace System.Web.DynamicData {
 
             public string Description {
                 get {
-                    return DisplayAttribute.GetPropertyValue(a => a.GetDescription(), null) ??
+                    return DisplayAttribute.GetLocalizedDescription() ??
                         DescriptionAttribute.GetPropertyValue(a => a.Description, null);
                 }
             }
@@ -599,14 +600,14 @@ namespace System.Web.DynamicData {
 
             public string DisplayName {
                 get {
-                    return DisplayAttribute.GetPropertyValue(a => a.GetName(), null) ??
+                    return DisplayAttribute.GetLocalizedName() ??
                         DisplayNameAttribute.GetPropertyValue(a => a.DisplayName, null);
                 }
             }
 
             public string ShortDisplayName {
                 get {
-                    return DisplayAttribute.GetPropertyValue(a => a.GetShortName(), null);
+                    return DisplayAttribute.GetLocalizedShortName();
                 }
             }
 
@@ -622,7 +623,7 @@ namespace System.Web.DynamicData {
 
             public string Prompt {
                 get {
-                    return DisplayAttribute.GetPropertyValue(a => a.GetPrompt(), null);
+                    return DisplayAttribute.GetLocalizedPrompt();
                 }
             }
 
index e0c957977bbfc80b809650cc258b8ae164a556ac..b7a62e03ad0c506d0e1a20b857e5d4ebdec818d4 100644 (file)
@@ -6,6 +6,7 @@
 #endregion
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Xml.Schema;
 using System.Xml.Serialization;
@@ -50,6 +51,7 @@ namespace Microsoft.VSDesigner.WCFModel
             return mapFile is DataSvcMapFile ? ((DataSvcMapFile)mapFile).Impl : null;
         }
 
+        [SuppressMessage("Microsoft.Security.Xml", "CA3060:UseXmlReaderForSchemaRead", Justification = "asp.net controls this .xsd file")]
         protected override XmlSchemaSet GetMapFileSchemaSet()
         {
             if (_mapFileSchemaSet == null)
index 9aea425a735756cc0d81906c657136bdd8cc6c91..d05896f21233975561d36eae46e62088df9efb86 100644 (file)
@@ -17,6 +17,7 @@ using XmlSerialization = System.Xml.Serialization;
 
 #if WEB_EXTENSIONS_CODE
 using System.Web.Resources;
+using System.Diagnostics.CodeAnalysis;
 #else
 using Microsoft.VSDesigner.WCF.Resources;
 #endif
@@ -551,6 +552,7 @@ namespace Microsoft.VSDesigner.WCFModel
         /// </summary>
         /// <param name="contentReader"></param>
         /// <remarks></remarks>
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")]
         private void LoadContentFromTextReader(TextReader contentReader)
         {
             if (contentReader == null)
@@ -597,6 +599,7 @@ namespace Microsoft.VSDesigner.WCFModel
         /// </summary>
         /// <return></return>
         /// <remarks></remarks>
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")]
         private MetadataContent LoadMetadataContent(MetadataType fileType)
         {
             if (ErrorInLoading != null)
index d820af9e042cb7eb24b07743c68ada8b6f6a3eac..8b9e1ea290916af1af40e266ad55872f21f14830 100644 (file)
@@ -6,6 +6,7 @@
 #endregion
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Xml.Schema;
 using System.Xml.Serialization;
@@ -50,6 +51,7 @@ namespace Microsoft.VSDesigner.WCFModel
             return mapFile is SvcMapFile ? ((SvcMapFile)mapFile).Impl : null;
         }
 
+        [SuppressMessage("Microsoft.Security.Xml", "CA3060:UseXmlReaderForSchemaRead", Justification = "asp.net controls this .xsd file")]
         protected override XmlSchemaSet GetMapFileSchemaSet()
         {
             if (_mapFileSchemaSet == null)
index 91b5f5e706bff36866ee9e647e2d574f9b22e106..a68af5f0a0f5554134464d04fbf3c97cceac5097 100644 (file)
@@ -59,7 +59,7 @@ namespace System.Web.UI.MobileControls.Adapters
 
         // This member variable is set each time when calendar info needs to
         // be accessed and be shared for other helper functions.
-        private Globalization.Calendar _threadCalendar;
+        private System.Globalization.Calendar _threadCalendar;
 
         private String _textBoxErrorMessage;
 
index ad6d1c2ff54d65774d1d745667637d804d175e04..c71652d11f158abc36395c55dc5d8e7e0577de52 100644 (file)
@@ -57,7 +57,7 @@ namespace System.Web.UI.MobileControls.Adapters
 
         // This member variable is set each time when calendar info needs to
         // be accessed and be shared for other helper functions.
-        private Globalization.Calendar _threadCalendar;
+        private System.Globalization.Calendar _threadCalendar;
 
         private String _textBoxErrorMessage;
 
index 47ceee67bd5751795e55e6503da3441f082d94b4..13648d0bf6cf2524f978eb526d5a674d37cb4f9e 100644 (file)
@@ -140,6 +140,10 @@ namespace System.Web {
         // Event signals that ASP.NET has started processing a request.
         // Overload used only for deducing ETW parameters; use the public entry point instead.
         //
+        // Visual Studio Online #222067 - This event is hardcoded to opt-out of EventSource activityID tracking. 
+        // This would normally be done by setting ActivityOptions = EventActivityOptions.Disable in the 
+        // Event attribute, but this causes a dependency between System.Web and mscorlib that breaks servicing. 
+        // 
         // !! WARNING !!
         // The logic in RequestStartedImpl must be kept in [....] with these parameters, otherwise
         // type safety violations could occur.
@@ -150,6 +154,10 @@ namespace System.Web {
         }
 
         // Event signals that ASP.NET has completed processing a request.
+        //
+        // Visual Studio Online #222067 - This event is hardcoded to opt-out of EventSource activityID tracking. 
+        // This would normally be done by setting ActivityOptions = EventActivityOptions.Disable in the 
+        // Event attribute, but this causes a dependency between System.Web and mscorlib that breaks servicing. 
         [Event((int)Events.RequestCompleted, Level = EventLevel.Informational, Task = (EventTask)Tasks.Request, Opcode = EventOpcode.Stop, Version = 1)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void RequestCompleted() {
index 60d00f6e84621d5a6a26235f0f76fd5ef96d75a7..9e137fd5fcd6692fa13709804b1d282e5e86bda9 100644 (file)
@@ -909,10 +909,11 @@ namespace System.Web.Caching {
             return false;
         }
 
-        //
-        //  This method will return only the file dependencies from this dependency
-        //
-        internal virtual string[] GetFileDependencies()
+        /// <summary>
+        /// This method will return only the file dependencies from this dependency
+        /// </summary>
+        /// <returns></returns>
+        public virtual string[] GetFileDependencies()
         {
 #if USE_MEMORY_CACHE
             if (CacheInternal.UseMemoryCache) {
@@ -1121,11 +1122,12 @@ namespace System.Web.Caching {
 
             return true;
         }
-
-        //
-        //  This method will return only the file dependencies from this dependency
-        //
-        internal override string[] GetFileDependencies()
+        /// <summary>
+        /// This method will return only the file dependencies from this dependency
+        /// </summary>
+        /// <returns></returns>
+        public override string[] GetFileDependencies()
         {
             ArrayList fileNames = null;
             CacheDependency[] dependencies = null;
index 993569bd85488c9d5c07d6ebcb26b790e883380d..4ecdaa430155cff11bd14790c571935389c57d6c 100644 (file)
@@ -10,6 +10,7 @@ namespace System.Web.Caching {
     internal class SRef {
         private static Type s_type = Type.GetType("System.SizedReference", true, false);
         private Object _sizedRef;
+        private long _lastReportedSize; // This helps tremendously when looking at large dumps
         
         internal SRef(Object target) {
             _sizedRef = HttpRuntime.CreateNonPublicInstance(s_type, new object[] {target});
@@ -24,7 +25,7 @@ namespace System.Web.Caching {
                                                _sizedRef, // target
                                                null, // args
                                                CultureInfo.InvariantCulture);
-                return (long) o;
+                return _lastReportedSize = (long) o;
             }
         }
         
index 811f6e7da2d18a1570ead26cd205524ed2bb6b53..0dd2f027e68e5d94f097a958d682f1b10dfaa53f 100644 (file)
@@ -519,13 +519,14 @@ namespace System.Web.Caching {
         internal Cache                      _cachePublic;
         internal protected CacheMemoryStats _cacheMemoryStats;
         private  object                     _timerLock = new object();
-        private  Timer                      _timer;
+        private  DisposableGCHandleRef<Timer> _timerHandleRef;
         private  int                        _currentPollInterval = MEMORYSTATUS_INTERVAL_30_SECONDS;
         internal int                        _inCacheManagerThread;
         internal bool                       _enableMemoryCollection;
         internal bool                       _enableExpiration;
         internal bool                       _internalConfigRead;
         internal SRefMultiple               _srefMultiple;
+        private  int                        _disposed = 0;
 
         internal CacheCommon() {
             _cachePublic = new Cache(0);
@@ -537,13 +538,16 @@ namespace System.Web.Caching {
 
         internal void Dispose(bool disposing) {
             if (disposing) {
-                EnableCacheMemoryTimer(false);
-                _cacheMemoryStats.Dispose();
+                // This method must be tolerant to multiple calls to Dispose on the same instance
+                if (Interlocked.Exchange(ref _disposed, 1) == 0) {
+                    EnableCacheMemoryTimer(false);
+                    _cacheMemoryStats.Dispose();
+                }
             }
         }
 
-        internal void AddSRefTarget(CacheInternal c) {
-            _srefMultiple.AddSRefTarget(c);
+        internal void AddSRefTarget(object o) {
+            _srefMultiple.AddSRefTarget(o);
         }
 
         internal void SetCacheInternal(CacheInternal cacheInternal) {
@@ -591,19 +595,20 @@ namespace System.Web.Caching {
                 
                 if (enable) {
                     
-                    if (_timer == null) {
+                    if (_timerHandleRef == null) {
                         // <cache privateBytesPollTime> has not been read yet
-                        _timer = new Timer(new TimerCallback(this.CacheManagerTimerCallback), null, _currentPollInterval, _currentPollInterval);
+                        Timer timer = new Timer(new TimerCallback(this.CacheManagerTimerCallback), null, _currentPollInterval, _currentPollInterval);
+                        _timerHandleRef = new DisposableGCHandleRef<Timer>(timer);
                         Debug.Trace("Cache", "Started CacheMemoryTimers");
                     }
                     else {
-                        _timer.Change(_currentPollInterval, _currentPollInterval);
+                        _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval);
                     }
                 }
                 else {
-                    Timer timer = _timer;
-                    if (timer != null && Interlocked.CompareExchange(ref _timer, null, timer) == timer) {
-                        timer.Dispose();
+                    var timerHandleRef = _timerHandleRef;
+                    if (timerHandleRef != null && Interlocked.CompareExchange(ref _timerHandleRef, null, timerHandleRef) == timerHandleRef) {
+                        timerHandleRef.Dispose();
                         Debug.Trace("Cache", "Stopped CacheMemoryTimers");
                     }
                 }
@@ -620,7 +625,7 @@ namespace System.Web.Caching {
         void AdjustTimer() {
             lock (_timerLock) {
 
-                if (_timer == null)
+                if (_timerHandleRef == null)
                     return;
 
                 // the order of these if statements is important
@@ -629,7 +634,7 @@ namespace System.Web.Caching {
                 if (_cacheMemoryStats.IsAboveHighPressure()) {
                     if (_currentPollInterval > MEMORYSTATUS_INTERVAL_5_SECONDS) {
                         _currentPollInterval = MEMORYSTATUS_INTERVAL_5_SECONDS;
-                        _timer.Change(_currentPollInterval, _currentPollInterval);
+                        _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval);
                     }
                     return;
                 }
@@ -641,7 +646,7 @@ namespace System.Web.Caching {
                     int newPollInterval = Math.Min(CacheMemorySizePressure.PollInterval, MEMORYSTATUS_INTERVAL_30_SECONDS);
                     if (_currentPollInterval != newPollInterval) {
                         _currentPollInterval = newPollInterval;
-                        _timer.Change(_currentPollInterval, _currentPollInterval);
+                        _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval);
                     }
                     return;
                 }
@@ -649,7 +654,7 @@ namespace System.Web.Caching {
                 // there is no pressure, interval should be the value from config
                 if (_currentPollInterval != CacheMemorySizePressure.PollInterval) {
                     _currentPollInterval = CacheMemorySizePressure.PollInterval;
-                    _timer.Change(_currentPollInterval, _currentPollInterval);
+                    _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval);
                 }
             }
         }
@@ -666,7 +671,7 @@ namespace System.Web.Caching {
 #endif
             try {
                 // Dev10 633335: if the timer has been disposed, return without doing anything
-                if (_timer == null)
+                if (_timerHandleRef == null)
                     return 0;
 
                 // The timer thread must always call Update so that the CacheManager
@@ -1188,7 +1193,7 @@ namespace System.Web.Caching {
             _usage = new CacheUsage(this);
             _lock = new object();
             _insertBlock = new ManualResetEvent(true);
-            cacheCommon.AddSRefTarget(this);
+            cacheCommon.AddSRefTarget(new { _entries, _expires, _usage });
         }
 
         /*
@@ -1880,24 +1885,32 @@ namespace System.Web.Caching {
 
     class CacheMultiple : CacheInternal {
         int             _disposed;
-        CacheSingle[]   _caches;
+        DisposableGCHandleRef<CacheSingle>[] _cachesRefs;
         int             _cacheIndexMask;
 
         internal CacheMultiple(CacheCommon cacheCommon, int numSingleCaches) : base(cacheCommon) {
             Debug.Assert(numSingleCaches > 1, "numSingleCaches is not greater than 1");
             Debug.Assert((numSingleCaches & (numSingleCaches - 1)) == 0, "numSingleCaches is not a power of 2");
             _cacheIndexMask = numSingleCaches - 1;
-            _caches = new CacheSingle[numSingleCaches];
+
+            // Each CacheSingle will have its own SRef reporting the size of the data it references.
+            // Objects in this CacheSingle may have refs to the root Cache and therefore reference other instances of CacheSingle.
+            // This leads to an unbalanced tree of SRefs and makes GC less efficient while calculating multiple SRefs on multiple cores.
+            // Using DisposableGCHandleRef here prevents SRefs from calculating data that does not belong to other CacheSingle instances.
+            _cachesRefs = new DisposableGCHandleRef<CacheSingle>[numSingleCaches];
             for (int i = 0; i < numSingleCaches; i++) {
-                _caches[i] = new CacheSingle(cacheCommon, this, i);
+                _cachesRefs[i] = new DisposableGCHandleRef<CacheSingle>(new CacheSingle(cacheCommon, this, i));
             }
         }
 
         protected override void Dispose(bool disposing) {
             if (disposing) {
                 if (Interlocked.Exchange(ref _disposed, 1) == 0) {
-                    foreach (CacheSingle cacheSingle in _caches) {
-                        cacheSingle.Dispose();
+                    foreach (var cacheSingleRef in _cachesRefs) {
+                        // Unfortunately the application shutdown logic allows user to access cache even after its disposal.
+                        // We'll keep the GCHandle inside cacheSingleRef until it gets reclaimed during appdomain shutdown.
+                        // And we'll only dispose the Target to preserve the old behavior.
+                        cacheSingleRef.Target.Dispose(); 
                     }
                 }
             }
@@ -1908,8 +1921,8 @@ namespace System.Web.Caching {
         internal override int PublicCount {
             get {
                 int count = 0;
-                foreach (CacheSingle cacheSingle in _caches) {
-                    count += cacheSingle.PublicCount;
+                foreach (var cacheSingleRef in _cachesRefs) {
+                    count += cacheSingleRef.Target.PublicCount;
                 }
 
                 return count;
@@ -1919,8 +1932,8 @@ namespace System.Web.Caching {
         internal override long TotalCount {
             get {
                 long count = 0;
-                foreach (CacheSingle cacheSingle in _caches) {
-                    count += cacheSingle.TotalCount;
+                foreach (var cacheSingleRef in _cachesRefs) {
+                    count += cacheSingleRef.Target.TotalCount;
                 }
 
                 return count;
@@ -1928,22 +1941,23 @@ namespace System.Web.Caching {
         }
 
         internal override IDictionaryEnumerator CreateEnumerator() {
-            IDictionaryEnumerator[] enumerators = new IDictionaryEnumerator[_caches.Length];
-            for (int i = 0, c = _caches.Length; i < c; i++) {
-                enumerators[i] = _caches[i].CreateEnumerator();
+            IDictionaryEnumerator[] enumerators = new IDictionaryEnumerator[_cachesRefs.Length];
+            for (int i = 0, c = _cachesRefs.Length; i < c; i++) {
+                enumerators[i] = _cachesRefs[i].Target.CreateEnumerator();
             }
 
             return new AggregateEnumerator(enumerators);
         }
 
         internal CacheSingle GetCacheSingle(int hashCode) {
-            Debug.Assert(_caches != null && _caches.Length != 0);
+            Debug.Assert(_cachesRefs != null && _cachesRefs.Length != 0);
             // Dev10 865907: Math.Abs throws OverflowException for Int32.MinValue
             if (hashCode < 0) {
                 hashCode = (hashCode == Int32.MinValue) ? 0 : -hashCode;
             }
             int index = (hashCode & _cacheIndexMask);
-            return _caches[index];
+            Debug.Assert(_cachesRefs[index].Target != null);
+            return _cachesRefs[index].Target;
         }
 
         internal override CacheEntry UpdateCache(
@@ -1960,15 +1974,15 @@ namespace System.Web.Caching {
 
         internal override long TrimIfNecessary(int percent) {
             long count = 0;
-            foreach (CacheSingle cacheSingle in _caches) {
-                count += cacheSingle.TrimIfNecessary(percent);
+            foreach (var cacheSingleRef in _cachesRefs) {
+                count += cacheSingleRef.Target.TrimIfNecessary(percent);
             }
             return count;
         }
 
         internal override void EnableExpirationTimer(bool enable) {
-            foreach (CacheSingle cacheSingle in _caches) {
-                cacheSingle.EnableExpirationTimer(enable);
+            foreach (var cacheSingleRef in _cachesRefs) {
+                cacheSingleRef.Target.EnableExpirationTimer(enable);
             }
         }
     }
index 9f26b6ed449d60e2c96baeff70f3bf474eaf9ecf..65f0272002f410cb2fa2a9ac6d2b7c2ef979c154 100644 (file)
@@ -2636,6 +2636,7 @@ namespace System.Web.Compilation {
         }
 
         [SuppressMessage("Microsoft.Security", "MSEC1207:UseXmlReaderForLoad", Justification = "Xml file is created by us and only accessible to admins.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Xml file is created by us and only accessible to admins.")]
         private static bool ReadPrecompMarkerFile(string appRoot, out bool updatable) {
 
             updatable = false;
index ebcce1503c3ae5e9da28467a561b4ea70b3d02ef..b190341670282e60011e0eabd24cb2c2997d29e2 100644 (file)
@@ -61,6 +61,7 @@ internal class PreservationFileReader {
     }
 
     [SuppressMessage("Microsoft.Security", "MSEC1207:UseXmlReaderForLoad", Justification = "Xml file is created by us and only accessible to admins.")]
+    [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Xml file is created by us and only accessible to admins.")]
     private BuildResult ReadFileInternal(VirtualPath virtualPath, string preservationFile, long hashCode, bool ensureIsUpToDate) {
 
         XmlDocument doc = new XmlDocument();
index 7802a250b5671824957e2e8728937232d1fbd480..949883305940491daecf94a0d5b5f8d336076343 100644 (file)
@@ -30,6 +30,7 @@ using TypedDataSetGenerator=System.Data.Design.TypedDataSetGenerator;
 internal class XsdBuildProvider: BuildProvider {
 
     [SuppressMessage("Microsoft.Security", "MSEC1207:UseXmlReaderForLoad", Justification = "Developer-controlled .xsd files in application directory are implicitly trusted by ASP.Net.")]
+    [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")]
     public override void GenerateCode(AssemblyBuilder assemblyBuilder)  {
 #if !FEATURE_PAL // FEATURE_PAL does not support System.Data.Design
         // Get the namespace that we will use
index 5dd5d4b54fdf4fc4e56425dd1db1e8902311c091..01ef95f8af74211a809c6637602c6949f0e2e9da 100644 (file)
@@ -32,6 +32,7 @@ namespace System.Web.Configuration {
 
     using Microsoft.Build.Utilities;
     using Microsoft.CSharp;
+    using System.Diagnostics.CodeAnalysis;
 
     [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
     [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
@@ -400,6 +401,7 @@ namespace System.Web.Configuration {
             return false;
         }
 
+        [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")]
         protected void ProcessBrowserFiles(bool useVirtualPath, string virtualDir) {
             _browserTree = new BrowserTree();
             _defaultTree = new BrowserTree();
@@ -507,6 +509,7 @@ namespace System.Web.Configuration {
             ProcessCustomBrowserFiles(false, String.Empty);
         }
 
+        [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")]
         internal void ProcessCustomBrowserFiles(bool useVirtualPath, string virtualDir) {
             //get all custom browser files and put them in the "tree"
             DirectoryInfo browserDirInfo = null;
index cddc9f294afffab1105f37117b926fd5c6679a51..2bd04aa4ba2e49c2f499baacd0ff7eb28e9c2749 100644 (file)
@@ -8,6 +8,7 @@ namespace System.Web.Configuration {
 
     using System.Collections;
     using System.Configuration;
+    using System.Diagnostics.CodeAnalysis;
     using System.IO;
     using System.Security;
     using System.Security.Permissions;
@@ -15,7 +16,6 @@ namespace System.Web.Configuration {
     using System.Web.Configuration;
     using System.Web.Util;
     using System.Xml;
-
     using Pair = System.Web.UI.Pair;
 
     //
@@ -276,6 +276,7 @@ namespace System.Web.Configuration {
         // 
         // ResolveFiles - parse files referenced with <file src="" />
         //
+        [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")]
         static void ResolveFiles(ParseState parseState, object configurationContext) {
 
             //
index 8100d4659163b587f546ccb46717938d108b9475..e40ceb29e5987a3e15eefdf6daa21232259d8c6a 100644 (file)
@@ -21,6 +21,7 @@ namespace System.Web.Configuration {
     using System.Security.AccessControl;
 #endif // !FEATURE_PAL
     using System.Security.Permissions;
+    using System.Diagnostics.CodeAnalysis;
 
 
 #if !FEATURE_PAL // FEATURE_PAL does not enable COM
@@ -215,6 +216,7 @@ namespace System.Web.Configuration {
             return sb.ToString();
         }
 
+        [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml", Justification = "Developer-controlled xml contents are implicitly trusted by ASP.Net.")]
         public string DoEncryptOrDecrypt(bool doEncrypt, string xmlString, string protectionProviderName, string protectionProviderType, string[] paramKeys, string[] paramValues)
         {
             Type t = Type.GetType(protectionProviderType, true);
index 5c74438c23ad3e63ccfe3916a5c77582161cb6b3..0534ff1c51d7439c995800b9fc69e248b18b781a 100644 (file)
@@ -6,11 +6,21 @@
 
 namespace System.Web.Handlers {
     using System;
+    using System.Threading.Tasks;
     using System.Web.Hosting;
-    
-    internal class TransferRequestHandler : IHttpHandler {
-        
-        public void ProcessRequest(HttpContext context) {
+
+    internal class TransferRequestHandler : IHttpAsyncHandler {
+        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
+        {
+            return TaskAsyncHelper.BeginTask(() => ProcessRequestAsync(context), cb, extraData);
+        }
+
+        public void EndProcessRequest(IAsyncResult result)
+        {
+            TaskAsyncHelper.EndTask(result);
+        }
+
+        private Task ProcessRequestAsync(HttpContext context) {
             IIS7WorkerRequest wr = context.WorkerRequest as IIS7WorkerRequest;
             if (wr == null) {
                 throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
@@ -24,14 +34,26 @@ namespace System.Web.Handlers {
                                   context.Request.EntityBody,
                                   null,
                                   preserveUser: false);
-            
+
             // force the completion of the current request so that the 
             // child execution can be performed immediately after unwind
-            context.ApplicationInstance.EnsureReleaseState();
+            var releaseStateTask = context.ApplicationInstance.EnsureReleaseStateAsync();
 
             // DevDiv Bugs 162750: IIS7 Integrated Mode:  TransferRequest performance issue
             // Instead of calling Response.End we call HttpApplication.CompleteRequest()
-            context.ApplicationInstance.CompleteRequest();
+            if (releaseStateTask.IsCompleted) {
+                context.ApplicationInstance.CompleteRequest();
+                return TaskAsyncHelper.CompletedTask;
+            }
+            else {
+                return releaseStateTask.ContinueWith((_) => context.ApplicationInstance.CompleteRequest());
+            }
+        }
+
+        public void ProcessRequest(HttpContext context)
+        {
+            string errorMessage = SR.GetString(SR.HttpTaskAsyncHandler_CannotExecuteSynchronously, GetType());
+            throw new NotSupportedException(errorMessage);
         }
 
         public bool IsReusable {
index e02ad7fb551d31eaa0e5ad8730f471d3434552d7..9a24a5b37f2abed7f6c1ee25b64758e2b3611d1d 100644 (file)
@@ -82,6 +82,9 @@ namespace System.Web.Hosting {
         // delegate OnRespondToPing
         private WaitCallback _onRespondToPingWaitCallback;
 
+        // flag indicates whether any fatal exception has been recorded
+        private bool _fatalExceptionRecorded = false;
+
         // single instance of app manager
         private static ApplicationManager _theAppManager;
 
@@ -154,6 +157,16 @@ namespace System.Web.Hosting {
             }
         }
 
+        private bool FatalExceptionRecorded
+        {
+            get {
+                return _fatalExceptionRecorded;
+            }
+            set {
+                _fatalExceptionRecorded = value;
+            }
+        }
+
         internal static void RecordFatalException(Exception e) {
             RecordFatalException(AppDomain.CurrentDomain, e);
         }
@@ -168,7 +181,7 @@ namespace System.Web.Hosting {
             }
         }
 
-        private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs eventArgs) {
+        internal static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs eventArgs) {
             // if the CLR is not terminating, ignore the notification
             if (!eventArgs.IsTerminating) {
                 return;
@@ -184,6 +197,15 @@ namespace System.Web.Hosting {
                 return;
             }
 
+            // If any fatal exception was recorded in applicaiton AppDomains,
+            // we wouldn't record exceptions in the default AppDomain. 
+            var appManager = GetApplicationManager();
+            if (AppDomain.CurrentDomain.IsDefaultAppDomain() && appManager.FatalExceptionRecorded) {
+                return;
+            }
+
+            appManager.FatalExceptionRecorded = true;
+
             RecordFatalException(appDomain, exception);
         }
 
index d5d2c15e352a8a9d843e51a7713ba89e1c73946c..27ce613025ec92382a446259c7297a7211bd35b0 100644 (file)
@@ -184,6 +184,11 @@ namespace System.Web.Hosting {
             // start watching for app domain unloading
             _onAppDomainUnload = new EventHandler(OnAppDomainUnload);
             Thread.GetDomain().DomainUnload += _onAppDomainUnload;
+
+            // VSO 160528: We used to listen to the default AppDomain's UnhandledException only.
+            // However, non-serializable exceptions cannot be passed to the default domain. Therefore
+            // we should try to log exceptions in application AppDomains.
+            Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(ApplicationManager.OnUnhandledException);
         }
 
         internal long TrimCache(int percent) {
index eff422558e332b96b845c2f140b46d0117076596..41564928cced4f99e96ceacbe00249c8cc3066cd 100644 (file)
@@ -500,17 +500,37 @@ namespace System.Web {
             }
         }
 
-        // DevDiv Bugs 151914: Release session state before executing child request
-        internal void EnsureReleaseState() {
+        private ISessionStateModule FindISessionStateModule() {
+            if (!HttpRuntime.UseIntegratedPipeline)
+                return null;
+
             if (_moduleCollection != null) {
                 for (int i = 0; i < _moduleCollection.Count; i++) {
-                    IHttpModule module = _moduleCollection.Get(i);
-                    if (module is SessionStateModule) {
-                        ((SessionStateModule) module).EnsureReleaseState(this);
-                        break;
+                    ISessionStateModule module = _moduleCollection.Get(i) as ISessionStateModule;
+                    if (module != null) {
+                        return module;
                     }
                 }
             }
+
+            return null;
+        }
+
+        // DevDiv Bugs 151914: Release session state before executing child request
+        internal void EnsureReleaseState() {
+            ISessionStateModule module = FindISessionStateModule();
+            if (module != null) {
+                module.ReleaseSessionState(Context);
+            }
+        }
+
+        internal Task EnsureReleaseStateAsync() {
+            ISessionStateModule module = FindISessionStateModule();
+            if (module != null) {
+                return module.ReleaseSessionStateAsync(Context);
+            }
+
+            return TaskAsyncHelper.CompletedTask;
         }
 
         /// <devdoc>
index 6d4bae316f5525cbafbb90706bfb4b13b4060257..f54da48a4aabddff3d23116e74b46c80b8b38e5e 100644 (file)
@@ -39,10 +39,11 @@ namespace System.Web {
             _ignoreParams = -1;
         }
 
-        /*
-         * Reset based on the cached vary headers.
-         */
-        internal void ResetFromParams(String[] parameters) {
+        /// <summary>
+        /// Set the Parameters in Cache Vary 
+        /// </summary>
+        /// <param name="parameters"></param>
+        public void SetParams(string[] parameters) {
             int i, n;
 
             Reset();
@@ -75,16 +76,20 @@ namespace System.Web {
             return _ignoreParams == 1 || _paramsStar || _parameters != null;
         }
 
-        internal String[] GetParams() {
-            String[]    s = null;
+        /// <summary>
+        /// Get the Parameters in Cache Vary
+        /// </summary>
+        /// <returns></returns>
+        public string[] GetParams() {
+            string[]    s = null;
             Object      item;
             int         i, j, c, n;
 
             if (_ignoreParams == 1) {
-                s =  new String[1] {String.Empty};
+                s =  new string[1] {string.Empty};
             }
             else if (_paramsStar) {
-                s =  new String[1] {"*"};
+                s =  new string[1] {"*"};
             }
             else if (_parameters != null) {
                 n = _parameters.Size;
@@ -102,7 +107,7 @@ namespace System.Web {
                     for (i = 0; i < n; i++) {
                         item = _parameters.GetValue(i);
                         if (item != null) {
-                            s[j] = (String) item;
+                            s[j] = (string) item;
                             j++;
                         }
                     }
@@ -116,7 +121,7 @@ namespace System.Web {
 
         //
         // Public methods and properties
-        //
+        // 
 
 
         /// <devdoc>
index 5cdde5d30067bf648131bb17ab7e515709b00edd..0e5efebd84fb5994eafe57bc4fd0ee17347c1138 100644 (file)
@@ -30,7 +30,7 @@ namespace System.Web {
     //
     // Public constants for cache-control
     //
-    
+
 
     /// <devdoc>
     ///    <para>
@@ -573,12 +573,10 @@ namespace System.Web {
 
             int i, n;
             string[] fields;
-            
-            _utcTimestampRequest = utcTimestampRequest;
-
-            _varyByContentEncodings.ResetFromContentEncodings(settings.VaryByContentEncodings);
-            _varyByHeaders.ResetFromHeaders(settings.VaryByHeaders);                          
-            _varyByParams.ResetFromParams(settings.VaryByParams);
+           
+            _varyByContentEncodings.SetContentEncodings(settings.VaryByContentEncodings);
+            _varyByHeaders.SetHeaders(settings.VaryByHeaders);                          
+            _varyByParams.SetParams(settings.VaryByParams);
 
             _isModified                       = settings.IsModified;                    
             _hasSetCookieHeader               = settings.hasSetCookieHeader;
@@ -645,7 +643,11 @@ namespace System.Web {
             }
         }
 
-        internal bool IsModified() {
+        /// <summary>
+        /// Return true if the CachePolicy has been modified
+        /// </summary>
+        /// <returns></returns>
+        public bool IsModified() {
             return _isModified || _varyByContentEncodings.IsModified() || _varyByHeaders.IsModified() || _varyByParams.IsModified();
         }
 
@@ -771,20 +773,18 @@ namespace System.Web {
                 return;
             }
 
-            Debug.Assert((_utcTimestampCreated == DateTime.MinValue && _utcTimestampRequest == DateTime.MinValue) ||
-                         (_utcTimestampCreated != DateTime.MinValue && _utcTimestampRequest != DateTime.MinValue),
-                        "_utcTimestampCreated and _utcTimestampRequest are out of [....] in UpdateCachedHeaders");
-
+            //To enable Out of Band OutputCache Module support, we will always refresh the UtcTimestampRequest.
             if (_utcTimestampCreated == DateTime.MinValue) {
-                _utcTimestampCreated = _utcTimestampRequest = response.Context.UtcTimestamp;
+                _utcTimestampCreated = response.Context.UtcTimestamp;
             }
+            _utcTimestampRequest = response.Context.UtcTimestamp; 
 
             if (_slidingExpiration != 1) {
                 _slidingDelta = TimeSpan.Zero;
             }
             else if (_isMaxAgeSet) {
                 _slidingDelta = _maxAge;
-            }
+            } 
             else if (_isExpiresSet) {
                 _slidingDelta = _utcExpires - _utcTimestampCreated;
             }
@@ -840,7 +840,7 @@ namespace System.Web {
                 }
 
                 sb.Append('\"');
-            }
+            } 
 
             if (_noStore) {
                 AppendValueToHeader(sb, "no-store");
@@ -1056,10 +1056,10 @@ namespace System.Web {
                 headers.Add(_headerVaryBy);
             }
         }
-
         /*
-         * Public methods
-         */
+        * Public methods
+        */
 
         internal HttpCachePolicySettings GetCurrentSettings(HttpResponse response) {
             String[]                    varyByContentEncodings;
@@ -1191,6 +1191,16 @@ namespace System.Web {
             return absoluteExpiration;
         }
 
+        // Expose this property to OutputCacheUtility class 
+        // In order to enable Out of Band output cache module to access the Validation Callback Info
+        internal IEnumerable GetValidationCallbacks() {
+            if (_validationCallbackInfo == null) {
+                return new ArrayList();
+            }
+
+            return _validationCallbackInfo;
+        }
+
         /*
          * Cache at server?
          */
@@ -1203,7 +1213,11 @@ namespace System.Web {
             _noServerCaching = true;
         }
 
-        internal bool GetNoServerCaching() {
+        /// <summary>
+        /// Return True if we should stops all server caching for current response
+        /// </summary>
+        /// <returns></returns>
+        public bool GetNoServerCaching() {
             return _noServerCaching;
         }
 
@@ -1229,6 +1243,13 @@ namespace System.Web {
             _varyByCustom = custom;
         }
 
+        /// <summary>
+        /// Get the Vary by Custom Value
+        /// </summary>
+        /// <returns></returns>
+        public string GetVaryByCustom() {
+            return _varyByCustom;
+        }
         /*
          * Cache-Control: extension        
          */
@@ -1250,6 +1271,14 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Get Cache Extensions Value
+        /// </summary>
+        /// <returns></returns>
+        public string GetCacheExtensions() {
+            return _cacheExtension;
+        }
+
         /*
          * Cache-Control: no-transform        
          */
@@ -1263,11 +1292,27 @@ namespace System.Web {
             _noTransforms = true;
         }
 
+        /// <summary>
+        /// Return true if No-transform directive, enables the sending of the CacheControl
+        /// </summary>
+        /// <returns></returns>
+        public bool GetNoTransforms() {
+            return _noTransforms;
+        }
+
         internal void SetIgnoreRangeRequests() {
             Dirtied();
             _ignoreRangeRequests = true;
         }
 
+        /// <summary>
+        /// Return true if ignore range request
+        /// </summary>
+        /// <returns></returns>
+        public bool GetIgnoreRangeRequests() {
+            return _ignoreRangeRequests;
+        }
+
         /// <devdoc>
         ///    <para>Contains policy for the Vary: header.</para>
         /// </devdoc>
@@ -1320,11 +1365,15 @@ namespace System.Web {
             }
         }
 
-        internal HttpCacheability GetCacheability() {
+        /// <summary>
+        /// Get the Cache-control (public, private and no-cache) directive
+        /// </summary>
+        /// <returns></returns>
+        public HttpCacheability GetCacheability() {
             return _cacheability;
         }
-
-
+        
+       
         /// <devdoc>
         ///    <para>Sets the Cache-Control header to one of the values of HttpCacheability in 
         ///       conjunction with a field-level exclusion directive.</para>
@@ -1376,6 +1425,14 @@ namespace System.Web {
             Dirtied();
             _hasUserProvidedDependencies = hasUserProvidedDependencies;
         }
+        
+        /// <summary>
+        /// return true if no store is set
+        /// </summary>
+        /// <returns></returns>
+        public bool GetNoStore() {
+            return _noStore;
+        }
 
         /*
          * Expiration policy.
@@ -1405,6 +1462,14 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Return the expire header as absolute expire datetime 
+        /// </summary>
+        /// <returns></returns>
+        public DateTime GetExpires() {
+            return _utcExpires;
+        }
+
         /*
          * Cache-Control: max-age=delta-seconds
          */
@@ -1428,6 +1493,14 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Get the Cache-Control Max Age
+        /// </summary>
+        /// <returns></returns>
+        public TimeSpan GetMaxAge() {
+            return _maxAge;
+        }       
+
         // Suppress max-age and s-maxage in cache-control header (required for IIS6 kernel mode cache)
         internal void SetNoMaxAgeInCacheControl() {
             _noMaxAgeInCacheControl = true;
@@ -1452,6 +1525,14 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Get the Cache-Control: Proxy Max Age Value
+        /// </summary>
+        /// <returns></returns>
+        public TimeSpan GetProxyMaxAge() {
+            return _proxyMaxAge;
+        }
+
         /*
          * Sliding Expiration
          */
@@ -1470,6 +1551,17 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Return true if to make expiration sliding. that is, if cached, it should be renewed with each
+        /// response. This feature is identical in spirit to the IIS
+        /// configuration option to add an expiration header relative to the current response
+        /// time. This feature is identical in spirit to the IIS configuration option to add
+        /// an expiration header relative to the current response time.
+        /// </summary>
+        /// <returns></returns>
+        public bool HasSlidingExpiration() {
+            return _slidingExpiration == 1;
+        }
 
         public void SetValidUntilExpires(bool validUntilExpires) {
             if (_validUntilExpires == -1 || _validUntilExpires == 1) {
@@ -1478,6 +1570,13 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Return true if valid until expires
+        /// </summary>
+        /// <returns></returns>
+        public bool IsValidUntilExpires() {
+            return _validUntilExpires == 1;
+        }
 
         public void SetAllowResponseInBrowserHistory(bool allow) {
             if (_allowInHistory == -1 || _allowInHistory == 1) {
@@ -1512,7 +1611,17 @@ namespace System.Web {
             }
         }
 
-        /*
+        /// <summary>
+        /// Get the Cache-Control: header to reflect either the must-revalidate or 
+        /// proxy-revalidate directives. 
+        /// The default is to not send either of these directives unless explicitly enabled using this method.
+        /// </summary>
+        /// <returns></returns>
+        public HttpCacheRevalidation GetRevalidation() {
+            return _revalidation;
+        }
+
+         /*
          * Etag
          */
 
@@ -1537,6 +1646,16 @@ namespace System.Web {
             _etag = etag;
         }
 
+        /// <summary>
+        /// Get the ETag header. Once an ETag is set, 
+        /// subsequent attempts to set it will fail and an exception will be thrown.
+        /// </summary>
+        /// <returns></returns>
+        public string GetETag() {
+            return _etag;
+        }
+
+
         /*
          * Last-Modified: RFC Date
          */
@@ -1577,6 +1696,14 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Get the Last-Modified header. 
+        /// </summary>
+        /// <returns></returns>
+        public DateTime GetUtcLastModified() {
+            return _utcLastModified;
+        }
+
 
         /// <devdoc>
         ///    <para>Sets the Last-Modified: header based on the timestamps of the
@@ -1587,6 +1714,15 @@ namespace System.Web {
             _generateLastModifiedFromFiles = true; 
         }
 
+        /// <summary>
+        /// Return true if the Last-Modified header is set to base on the timestamps of the
+        /// file dependencies of the handler.
+        /// </summary>
+        /// <returns></returns>
+        public bool GetLastModifiedFromFileDependencies() {
+            return _generateLastModifiedFromFiles;
+        }
+
 
         /// <devdoc>
         ///    <para>Sets the Etag header based on the timestamps of the file 
@@ -1601,6 +1737,14 @@ namespace System.Web {
             _generateEtagFromFiles = true;         
         }
 
+        /// <summary>
+        /// Return true if the Etag header has been set to base on the timestamps of the file 
+        /// dependencies of the handler
+        /// </summary>
+        /// <returns></returns>
+        public bool GetETagFromFileDependencies() {
+            return _generateEtagFromFiles;
+        }
 
         public void SetOmitVaryStar(bool omit) {
             Dirtied();
@@ -1610,6 +1754,13 @@ namespace System.Web {
             }
         }
 
+        /// <summary>
+        /// Return true if to omit Vary Star
+        /// </summary>
+        /// <returns></returns>
+        public int GetOmitVaryStar() {
+            return _omitVaryStar;
+        }
 
         /// <devdoc>
         ///    <para>Registers a validation callback for the current response.</para>
@@ -1628,5 +1779,16 @@ namespace System.Web {
 
             _validationCallbackInfo.Add(new ValidationCallbackInfo(handler, data));
         }
+        /// <summary>
+        /// Utc Timestamp Created
+        /// </summary>
+        public DateTime UtcTimestampCreated {
+            get {
+                return _utcTimestampCreated;
+            }
+            set {
+                _utcTimestampCreated = value;
+            }
+        }
     }
 }
index e55c71d05148c19a049c07d722bcf4eec781ad17..7f8a952f00432ae2e95125e57247fe18497c8fa8 100644 (file)
@@ -37,10 +37,12 @@ namespace System.Web {
             _headers = null;
         }
 
-        /*
-         * Reset based on the cached vary headers.
-         */
-        internal void ResetFromHeaders(String[] headers) {
+        /// <summary>
+        /// Set the Headers in Cache Vary
+        /// </summary>
+        /// <param name="headers"></param>
+        public void SetHeaders(string[] headers) {
+
             int i, n;
 
             if (headers == null) {
@@ -48,7 +50,7 @@ namespace System.Web {
                 _varyStar = false;
                 _headers = null;
             }
-            else {
+            else {           
                 _isModified = true;
                 if (headers[0].Equals("*")) {
                     Debug.Assert(headers.Length == 1, "headers.Length == 1");
@@ -97,19 +99,19 @@ namespace System.Web {
 
             return null;
         }
+        /// <summary>
+        /// Get the Headers in Cache Vary
+        /// </summary>
+        /// <returns></returns>
+        public string[] GetHeaders() {
+            string[]    s = null;
 
-        /*
-         * Returns the headers, for package access only.
-         * 
-         * @return the headers.
-         */
-        internal String[] GetHeaders() {
-            String[]    s = null;
             Object      item;
             int         i, j, c, n;
 
             if (_varyStar) {
-                return new String[1] {"*"};
+                return new string[1] {"*"};
             }
             else if (_headers != null) {
                 n = _headers.Size;
@@ -127,7 +129,7 @@ namespace System.Web {
                     for (i = 0; i < n; i++) {
                         item = _headers.GetValue(i);
                         if (item != null) {
-                            s[j] = (String) item;
+                            s[j] = (string) item;
                             j++;
                         }
                     }
@@ -138,7 +140,7 @@ namespace System.Web {
 
             return s;
         }
-
+  
         //
         // Public methods and properties
         //
index fe1e6d355f28e0e68606c04f997232206bf41139..236adffa9a0c137c2642cbcf61e699f093f5ffe5 100644 (file)
@@ -32,11 +32,13 @@ namespace System.Web {
             _isModified = false;
             _contentEncodings = null;
         }
+  
+        /// <summary>
+        /// Set the Content Encodings in Cache Vary
+        /// </summary>
+        /// <param name="contentEncodings"></param>
+        public void SetContentEncodings(string[] contentEncodings) {
 
-        /*
-         * Reset based on content encodings.
-         */
-        internal void ResetFromContentEncodings(String[] contentEncodings) {
             Reset();
             if (contentEncodings != null) {
                 _isModified = true;
@@ -75,9 +77,18 @@ namespace System.Web {
         internal bool IsModified() {
             return _isModified;
         }
-
-        internal String[] GetContentEncodings() {
-            return _contentEncodings;
+               
+        /// <summary>
+        /// Get the Content Encodings in Cache Vary
+        /// </summary>
+        /// <returns></returns>
+        public string[] GetContentEncodings() {
+            if (_contentEncodings != null) {
+                string[] contentEncodings = new string[_contentEncodings.Length];
+                _contentEncodings.CopyTo(contentEncodings, 0);
+                return contentEncodings;
+            }
+            return null;
         }
 
         //
index 4d02a0a8a8f726284a0931d2681dde864ba6c0f9..812c779064eae62c39c447e7cd4877dfa9dbcac5 100644 (file)
@@ -22,6 +22,7 @@ namespace System.Web {
     using System.Linq;
     using System.Net;
     using System.Reflection;
+    using System.Runtime.CompilerServices;
     using System.Runtime.Remoting.Messaging;
     using System.Security.Permissions;
     using System.Security.Principal;
@@ -1009,6 +1010,8 @@ namespace System.Web {
                 if (_delayedSessionState) {
                     lock (this) {
                         if (_delayedSessionState) {
+                            Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null");
+
                             // If it's not null, it means we have a delayed session state item
                             _sessionStateModule.InitStateStoreItem(true);
                             _delayedSessionState = false;
@@ -1020,8 +1023,21 @@ namespace System.Web {
             }
         }
 
+        [MethodImpl(MethodImplOptions.NoInlining)]
         internal void EnsureSessionStateIfNecessary() {
-            Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null");
+            if (_sessionStateModule == null)
+            {
+                // If _sessionStateModule is null, we wouldn't be able to call 
+                // _sessionStateModule.EnsureStateStoreItemLocked(), so we return here.
+                // _sessionStateModule could be null in the following cases,
+                // 1. No session state acquired.
+                // 2. HttpResponse.Flush() happens after session state being released.
+                // 3. The session state module in use is not System.Web.SessionState.SessionStateModule.
+                //
+                // This method is for the in-framework SessionStateModule only.
+                //  OOB SessionStateModule can achieve this by using HttpResponse.AddOnSendingHeaders. 
+                return;
+            }
 
             HttpSessionState session = (HttpSessionState)Items[SessionStateUtility.SESSION_KEY];
 
@@ -1042,7 +1058,6 @@ namespace System.Web {
         }
 
         internal void RemoveHttpSessionStateModule() {
-            Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null");
             _delayedSessionState = false;
             _sessionStateModule = null;
         }
index b92ce62520ba19dc4df09601e85545381237d6a8..db4f721437c45c7d9fe7606f9d2221e0256a32a8 100644 (file)
@@ -1126,9 +1126,18 @@ namespace System.Web {
             }
 
             // restore content
-            _httpWriter.UseSnapshot(rawResponse.Buffers);
+            SetResponseBuffers(rawResponse.Buffers);
+  
+            _suppressContent = !sendBody;         
+        }
+
+        // set the response content bufffers
+        internal void SetResponseBuffers(ArrayList buffers) {
+            if (_httpWriter == null) {
+                throw new HttpException(SR.GetString(SR.Cannot_use_snapshot_for_TextWriter));
+            }
 
-            _suppressContent = !sendBody;
+            _httpWriter.UseSnapshot(buffers);
         }
 
         internal void CloseConnectionAfterError() {
index aa91b33062724c2c6bc965678c94b11b7582b463..3c0296df9e3277543b183e0803040ccc37070226 100644 (file)
@@ -4,6 +4,7 @@
     using System.ComponentModel;
     using System.ComponentModel.DataAnnotations;
     using System.Linq;
+    using System.Web.Globalization;
 
     public class DataAnnotationsModelMetadataProvider : AssociatedMetadataProvider {
 
@@ -11,7 +12,7 @@
             List<Attribute> attributeList = new List<Attribute>(attributes);
             DisplayColumnAttribute displayColumnAttribute = attributeList.OfType<DisplayColumnAttribute>().FirstOrDefault();
             DataAnnotationsModelMetadata result = new DataAnnotationsModelMetadata(this, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute);
-
+            
 #if UNDEF
             // Do [HiddenInput] before [UIHint], so you can override the template hint
             HiddenInputAttribute hiddenInputAttribute = attributeList.OfType<HiddenInputAttribute>().FirstOrDefault();
             DisplayAttribute display = attributes.OfType<DisplayAttribute>().FirstOrDefault();
             string name = null;
             if (display != null) {
-                result.Description = display.GetDescription();
-                result.ShortDisplayName = display.GetShortName();
-                result.Watermark = display.GetPrompt();
-                result.Order = display.GetOrder() ?? ModelMetadata.DefaultOrder;
+                var displayAdapter = new DisplayAttributeAdapter(display);
+                result.Description = displayAdapter.GetDescription();
+                result.ShortDisplayName = displayAdapter.GetShortName();
+                result.Watermark = displayAdapter.GetPrompt();
+                result.Order = displayAdapter.GetOrder() ?? ModelMetadata.DefaultOrder;
 
-                name = display.GetName();
+                name = displayAdapter.GetName();
             }
 
             if (name != null) {
index cff887cbb5f0f49dc997d69c965bf79d4b0bab7f..79bf561a2ad58f0bf027b96174d0c52f5badda7d 100644 (file)
@@ -2,8 +2,10 @@
     using System;
     using System.Collections.Generic;
     using System.ComponentModel.DataAnnotations;
+    using System.Threading;
+    using System.Web.Globalization;
 
-    public class DataAnnotationsModelValidator : ModelValidator {
+    public class DataAnnotationsModelValidator : ModelValidator {        
         public DataAnnotationsModelValidator(ModelMetadata metadata, ModelBindingExecutionContext context, ValidationAttribute attribute)
             : base(metadata, context) {
 
 
         protected internal string ErrorMessage {
             get {
-                return Attribute.FormatErrorMessage(Metadata.GetDisplayName());
+                if (UseStringLocalizerProvider) {
+                    var errorMsg = GetLocalizedString(Attribute.ErrorMessage);
+
+                    return errorMsg ?? Attribute.FormatErrorMessage(Metadata.GetDisplayName());
+                }
+                else {
+                    return Attribute.FormatErrorMessage(Metadata.GetDisplayName());
+                }
+            }
+        }
+
+        protected string GetLocalizedString(string name, params object[] arguments) {
+            if (StringLocalizerProviders.DataAnnotationStringLocalizerProvider != null) {
+                return StringLocalizerProviders.DataAnnotationStringLocalizerProvider
+                    .GetLocalizedString(Thread.CurrentThread.CurrentUICulture, name, arguments);
+            }
+            else {
+                return null;
             }
         }
 
             ValidationResult result = Attribute.GetValidationResult(Metadata.Model, context);
             if (result != ValidationResult.Success) {
                 yield return new ModelValidationResult {
-                    Message = result.ErrorMessage
+                    Message = GetValidationErrorMessage(result)
                 };
             }
         }
+
+        protected virtual string GetLocalizedErrorMessage(string errorMessage) {
+            return GetLocalizedString(errorMessage, Metadata.GetDisplayName());
+        }
+
+        private string GetValidationErrorMessage(ValidationResult result) {
+            string errorMsg;
+
+            if (UseStringLocalizerProvider) {
+                errorMsg = GetLocalizedErrorMessage(Attribute.ErrorMessage);
+
+                errorMsg = errorMsg ?? result.ErrorMessage;
+            }
+            else {
+                errorMsg = result.ErrorMessage;
+            }
+            return errorMsg;
+        }
+
+        private bool UseStringLocalizerProvider {
+            get {
+                // if developer already uses existing localization feature,
+                // then we don't opt in the new localization feature.
+                return (!string.IsNullOrEmpty(Attribute.ErrorMessage) &&
+                    string.IsNullOrEmpty(Attribute.ErrorMessageResourceName) &&
+                    Attribute.ErrorMessageResourceType == null);
+            }
+        }
     }
 }
index 11cce2416e25ce9d3bf4ed1d8f582d1041d00b34..ae952e12a8c6655aec5c817b336bbc3a2c8de951 100644 (file)
@@ -1,5 +1,5 @@
 namespace System.Web.ModelBinding {
-    using System;
+using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.Diagnostics.CodeAnalysis;
@@ -7,6 +7,7 @@ using System.Globalization;
 using System.Linq;
 using System.Reflection;
 using System.Threading;
+using System.Web.Globalization;
 
     // A factory for validators based on ValidationAttribute
     public delegate ModelValidator DataAnnotationsModelValidationFactory(ModelMetadata metadata, ModelBindingExecutionContext context, ValidationAttribute attribute);
@@ -26,7 +27,7 @@ using System.Threading;
     public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider {
         private static bool _addImplicitRequiredAttributeForValueTypes = true;
         private static ReaderWriterLockSlim _adaptersLock = new ReaderWriterLockSlim();
-
+        
         // Factories for validation attributes
 
         internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory =
@@ -49,6 +50,14 @@ using System.Threading;
                 typeof(StringLengthAttribute),
                 (metadata, context, attribute) => new StringLengthAttributeAdapter(metadata, context, (StringLengthAttribute)attribute)
             },
+            {
+                typeof(MinLengthAttribute),
+                (metadata, context, attribute) => new MinLengthAttributeAdapter(metadata, context, (MinLengthAttribute)attribute)
+            },
+            {
+                typeof(MaxLengthAttribute),
+                (metadata, context, attribute) => new MaxLengthAttributeAdapter(metadata, context, (MaxLengthAttribute)attribute)
+            },
         };
 
         // Factories for IValidatableObject models
@@ -66,7 +75,7 @@ using System.Threading;
                 _addImplicitRequiredAttributeForValueTypes = value;
             }
         }
-
+        
         protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ModelBindingExecutionContext context, IEnumerable<Attribute> attributes) {
             _adaptersLock.EnterReadLock();
 
index 2c5acf046fca199103066f549d8285d231565ca9..28858643c11e2dbe144c3a5fbbb689b250c9e52e 100644 (file)
@@ -6,6 +6,11 @@
             : base(metadata, context, attribute) {
         }
 
+        protected override string GetLocalizedErrorMessage(string errorMessage) {
+            return GetLocalizedString(errorMessage, Metadata.GetDisplayName(), Attribute.Minimum, Attribute.Maximum);
+
+        }
+
 #if UNDEF
         public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
             string errorMessage = ErrorMessage; // Per Dev10 Bug #923283, need to make sure ErrorMessage is called before Minimum/Maximum
index c5c0f0d527f4261668bc06a4a86c46faa6d5d72d..2a49853c2f6e98e5780a287b7aeb5f3216b1979d 100644 (file)
@@ -6,6 +6,10 @@
             : base(metadata, context, attribute) {
         }
 
+        protected override string GetLocalizedErrorMessage(string errorMessage) {
+            return GetLocalizedString(errorMessage, Metadata.GetDisplayName(), Attribute.Pattern);
+        }
+
 #if UNDEF
         public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
             return new[] { new ModelClientValidationRegexRule(ErrorMessage, Attribute.Pattern) };
index 354cc3a86178ffecf4c4af0f91105e8cedcf5cd1..a27cba17dfbd3337e5085ba2c5038efd62acb7f0 100644 (file)
@@ -6,6 +6,10 @@
             : base(metadata, context, attribute) {
         }
 
+        protected override string GetLocalizedErrorMessage(string errorMessage) {            
+            return GetLocalizedString(errorMessage, Metadata.GetDisplayName(), Attribute.MinimumLength, Attribute.MaximumLength);
+        }
+
 #if UNDEF
         public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
             return new[] { new ModelClientValidationStringLengthRule(ErrorMessage, Attribute.MinimumLength, Attribute.MaximumLength) };
index a4fcc08f63c7c19823cd6303411c347a549beba7..a4147901f2e09e42749cd950026377c1d086fd6d 100644 (file)
@@ -44,6 +44,7 @@ namespace System.Web.Security.Cryptography {
             return new DESCryptoServiceProvider();
         }
 
+        [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:SHA1CannotBeUsed", Justification = @"This is only used by legacy code; new features do not use this algorithm.")]
         internal static HMACSHA1 CreateHMACSHA1() {
             return new HMACSHA1();
         }
index 2fba9c4592a836f6311ef1d1aec55dc96272e24b..a07c223408de8855bd2440783fe54eaf4ef3148f 100644 (file)
@@ -17,6 +17,7 @@ namespace System.Web.Security {
     using System.Security;
     using System.Security.Claims;
     using System.Security.Permissions;
+    using System.Security.Principal;
 
     /// <devdoc>
     ///    This class is an IIdentity derived class
@@ -77,7 +78,7 @@ namespace System.Web.Security {
         ///    Constructor.
         /// </devdoc>
         protected FormsIdentity(FormsIdentity identity)
-            : base(identity)
+            : base((IIdentity)identity)
         {
             _Ticket = identity._Ticket;
         }
index 2e9144cceb448469f4143d3a3b6822d4980f9518..84b3d55a8ae28436482c2b8b8ae69f352d2d7c1e 100644 (file)
@@ -27,6 +27,7 @@ namespace System.Web.SessionState {
     using System.Globalization;
     using System.Security.Permissions;
     using System.Text;
+    using System.Threading.Tasks;
     using System.Web.Hosting;
     using System.Web.Management;
     using Microsoft.Win32;
@@ -111,7 +112,7 @@ namespace System.Web.SessionState {
     /// <devdoc>
     ///    <para>[To be supplied.]</para>
     /// </devdoc>
-    public sealed class SessionStateModule : IHttpModule {
+    public sealed class SessionStateModule : ISessionStateModule {
 
         internal const string SQL_CONNECTION_STRING_DEFAULT = "data source=localhost;Integrated Security=SSPI";
         internal const string STATE_CONNECTION_STRING_DEFAULT = "tcpip=loopback:42424";
@@ -1446,15 +1447,19 @@ namespace System.Web.SessionState {
                 }
             }
         }
-
-        // DevDiv Bugs 151914: Release session state before executing child request
-        internal void EnsureReleaseState(HttpApplication app) {
+        
+        public void ReleaseSessionState(HttpContext context) {
             if (HttpRuntime.UseIntegratedPipeline && _acquireCalled && !_releaseCalled) {
                 try {
-                    OnReleaseState(app, null);
+                    OnReleaseState(context.ApplicationInstance, null);
                 }
                 catch { }
             }
         }
+
+        public Task ReleaseSessionStateAsync(HttpContext context) {
+            ReleaseSessionState(context);
+            return TaskAsyncHelper.CompletedTask;
+        }
     }
 }
index 8116fbc2711df3d1984ec20874f6c0ac70212a68..19c6d73938a27d0881b8adff81c2e614767dd234 100644 (file)
@@ -73,6 +73,24 @@ namespace System.Web.SessionState {
             return context.Application.SessionStaticObjects.Clone();
         }
 
+        /// <summary>
+        /// Gets a value that indicates whether session state is required by the context.
+        /// </summary>
+        /// <param name="context">The HttpContext.</param>
+        /// <returns>A value that indicates whether session state is required by the context.</returns>
+        static public bool IsSessionStateRequired(HttpContext context) {
+            return context.RequiresSessionState;
+        }
+
+        /// <summary>
+        /// Gets a value that indicates whether session state is read-only in the context.
+        /// </summary>
+        /// <param name="context">The HttpContext.</param>
+        /// <returns>A value that indicates whether session state is read-only in the context.</returns>
+        static public bool IsSessionStateReadOnly(HttpContext context) {
+            return context.ReadOnlySessionState;
+        }
+
         internal static SessionStateStoreData CreateLegitStoreData(HttpContext context,
                                                     ISessionStateItemCollection sessionItems,
                                                     HttpStaticObjectsCollection staticObjects,
index 2558f75a0d545dfad80fce98e9b99105855872d2..85e2bef8a0583a96356dc87ec53d58a7d3d1b1e9 100644 (file)
@@ -16,6 +16,8 @@ namespace System.Web {
 
     internal static class TaskAsyncHelper {
 
+        private static readonly Task s_completedTask = Task.FromResult<object>(null);
+
         internal static IAsyncResult BeginTask(Func<Task> taskFunc, AsyncCallback callback, object state) {
             Task task = taskFunc();
             if (task == null) {
@@ -76,5 +78,10 @@ namespace System.Web {
             taskWrapper.Task.GetAwaiter().GetResult();
         }
 
+        internal static Task CompletedTask {
+            get {
+                return s_completedTask;
+            }
+        }
     }
 }
index 9efc13a5871cd9d0a7844cdd59d980915ab4c2ed..e70f02a264dcbbb5444a0e8444bf669d9b864036 100644 (file)
@@ -6,27 +6,27 @@
 
 namespace System.Web.UI {
 
-using System;
-using System.IO;
-using System.Text;
-using System.Collections;
-using System.Collections.Specialized;
-using System.ComponentModel;
-using System.ComponentModel.Design;
-using System.Globalization;
-using System.Web;
-using System.Web.Util;
-using System.Web.UI.HtmlControls;
-using System.Web.UI.WebControls;
-using System.Web.Caching;
-using System.Web.Compilation;
-using System.Web.Configuration;
-using System.Security.Permissions;
-
-
-// Keeps track of one call to Page Register* API
-// The semantics of the fields depends to the call type
-[Serializable]
+    using System;
+    using System.IO;
+    using System.Text;
+    using System.Collections;
+    using System.Collections.Specialized;
+    using System.ComponentModel;
+    using System.ComponentModel.Design;
+    using System.Globalization;
+    using System.Web;
+    using System.Web.Util;
+    using System.Web.UI.HtmlControls;
+    using System.Web.UI.WebControls;
+    using System.Web.Caching;
+    using System.Web.Compilation;
+    using System.Web.Configuration;
+    using System.Security.Permissions;
+
+
+    // Keeps track of one call to Page Register* API
+    // The semantics of the fields depends to the call type
+    [Serializable]
 internal class RegisterCallData {
     internal ClientAPIRegisterType Type;
     internal ScriptKey Key;
@@ -406,8 +406,8 @@ public abstract class BasePartialCachingControl : Control {
         }
         else {
             string[] varyByParams = null;
-            if (_varyByParamsCollection != null)
-                varyByParams = _varyByParamsCollection.GetParams();
+                if (_varyByParamsCollection != null)
+                    varyByParams = _varyByParamsCollection.GetParams();
 
             cachedVary = new ControlCachedVary(varyByParams, _varyByControlsCollection, _varyByCustom);
 
@@ -576,7 +576,7 @@ public abstract class BasePartialCachingControl : Control {
 
         string[] varyByParamsStrings = varyByParams.Split(varySeparator);
         _varyByParamsCollection = new HttpCacheVaryByParams();
-        _varyByParamsCollection.ResetFromParams(varyByParamsStrings);
+        _varyByParamsCollection.SetParams(varyByParamsStrings);
     }
 
     internal void RegisterPostBackScript() {
index ce3d85949f0cc2263e3fdf9fe91230c5517ce1f5..ea3c1e08be941ae76a3f8402b8eb4989622edf97 100644 (file)
@@ -56,7 +56,7 @@ namespace System.Web.UI.WebControls {
 
         private ArrayList dateList;
         private SelectedDatesCollection selectedDates;
-        private Globalization.Calendar threadCalendar;
+        private System.Globalization.Calendar threadCalendar;
         private DateTime minSupportedDate;
         private DateTime maxSupportedDate;
 #if DEBUG
index ac1bbae574dd96e1fa57c4a0acd24a4e34554e32..3657d75cca437065bc28d7c3866d29963821406a 100644 (file)
@@ -32,7 +32,17 @@ namespace System.Web.UI.WebControls {
             }
 
             ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
-            MemberExpression property = Expression.Property(parameter, sortExpression);
+            //VSO bug 173528-- Add support for sorting by nested property names
+            MemberExpression property = null;
+            string[] sortExpressionFields = sortExpression.Split('.');
+            foreach (string sortExpressionField in sortExpressionFields) {
+                if (property == null) {
+                    property = Expression.Property(parameter, sortExpressionField);
+                }
+                else {
+                    property = Expression.Property(property, sortExpressionField);
+                }
+            }
             LambdaExpression lambda = Expression.Lambda(property, parameter);
 
             string methodName = (isDescending) ? "OrderByDescending" : "OrderBy" ;
index bb97a7c282399745e85290c6c23145df6cbf5a9d..93ec3e60d03d5c6d29b648612006708d593b331c 100644 (file)
@@ -41,6 +41,7 @@ namespace System.Web.UI.WebControls {
 
 
         [SuppressMessage("Microsoft.Security", "MSEC1220:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
         public override void SetTagInnerText(string text) {
             if (!Util.IsWhiteSpaceString(text)) {
 
@@ -114,7 +115,9 @@ namespace System.Web.UI.WebControls {
 #pragma warning restore 0618
 
         [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "_identityTransform contents are trusted hard-coded string.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "_identityTransform contents are trusted hard-coded string.")]
         [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "_identityTransform contents are trusted hard-coded string.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "_identityTransform contents are trusted hard-coded string.")]
         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
         static Xml() {
 
@@ -332,6 +335,7 @@ namespace System.Web.UI.WebControls {
 
 
         [SuppressMessage("Microsoft.Security", "MSEC1218:ReviewWebControlForSet_DocumentContent", Justification = "Legacy code that trusts our developer input.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3067:ReviewWebControlForSet_DocumentContent", Justification = "Legacy code that trusts our developer input.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         protected override void AddParsedSubObject(object obj) {
             if (obj is LiteralControl) {
                 // Trim the initial whitespaces since XML is very picky (related to ASURT 58100)
index 0e48e6d162cbf13fb62caa3298b96cc27d5c75af..f6c84a217757af719de2a160e6eb411d5a4adc14 100644 (file)
@@ -36,4 +36,33 @@ namespace System.Web.Util {
         }
 
     }
+
+    // This wrapper around a managed object is opaque to SizedReference GC handle
+    // and therefore helps with calculating size of only relevant graph of objects
+    internal class DisposableGCHandleRef<T> : IDisposable
+    where T : class, IDisposable {
+        GCHandle _handle;
+        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+        public DisposableGCHandleRef(T t) {
+            Debug.Assert(t != null);
+            _handle = GCHandle.Alloc(t);
+        }
+
+        public T Target {
+            [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+            get {
+                Debug.Assert(_handle.IsAllocated);
+                return (T)_handle.Target;
+            }
+        }
+
+        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+        public void Dispose() {
+            Target.Dispose();
+            Debug.Assert(_handle.IsAllocated);
+            if (_handle.IsAllocated) {
+                _handle.Free();
+            }
+        }
+    }
 }
index 545023b7a24b33f9762124c028e1ad33fcaf10d6..94ef87f0291332ce2216ad140596e200ba485631 100644 (file)
@@ -15,6 +15,7 @@ using System.Text;
 using System.Globalization;
 using System.Runtime.InteropServices;
 using System.Web.Hosting;
+using System.Diagnostics.CodeAnalysis;
 
 /*
  * Various string handling utilities
@@ -294,6 +295,7 @@ internal static class StringUtil {
     // Instead use the default AppDomain, because it doesn't have string hash randomization enabled.
     // Marshal the call to reuse the default StringComparer behavior. 
     // PERF isn't optimal, so apply consideration!
+    [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "We carefully control the callers.")]
     internal static int GetNonRandomizedStringComparerHashCode(string s) {
         // Preserve the default behavior when string hash randomization is off
         if (!AppSettings.UseRandomizedStringHashAlgorithm) {
index d442f0cc89cad5250d70915b808f5a0f7e0ae1d7..64a86b68118339c8fe106aaf76eca8c62dff948c 100644 (file)
@@ -105,7 +105,7 @@ namespace System.Web.Util {
             // This method only schedules work; it doesn't itself do any work. The lock is held for a very
             // short period of time.
             lock (_lockObj) {
-                Task newTask = _lastScheduledTask.ContinueWith(_ => SafeWrapCallback(action));
+                Task newTask = _lastScheduledTask.ContinueWith(_ => SafeWrapCallback(action), TaskScheduler.Default);
                 _lastScheduledTask = newTask; // the newly-created task is now the last one
             }
         }
index eb237040da08bcee7d6385cdac2eef0d76fae682..a07e9df58d2232fc8e0b17e468ed5feef46127bd 100644 (file)
@@ -17,6 +17,7 @@ namespace System.Web.Util {
         public static readonly long MaxEntityExpansion = 1024 * 1024;
 
         [SuppressMessage("Microsoft.Security", "MSEC1208:DoNotUseLoadXml", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         public static XmlDocument CreateXmlDocumentFromContent(string content)
         {
             XmlDocument doc = new XmlDocument();
@@ -35,6 +36,7 @@ namespace System.Web.Util {
         }
 
         [SuppressMessage("Microsoft.Security", "MSEC1210:UseXmlReaderForXPathDocument", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3059:UseXmlReaderForXPathDocument", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         public static XPathDocument CreateXPathDocumentFromContent(string content)
         {
             StringReader reader = new StringReader(content);
@@ -47,6 +49,7 @@ namespace System.Web.Util {
         }
 
         [SuppressMessage("Microsoft.Security", "MSEC1220:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
         public static XmlReaderSettings CreateXmlReaderSettings()
         {
             XmlReaderSettings settings = new XmlReaderSettings();
@@ -68,7 +71,9 @@ namespace System.Web.Util {
         // try to guess at how to set matching defaults with XmlReader.Create().
         // (E.g. DtdProcessing is Parse by default using XmlTextReader directly.  It's Prohibit in default XmlReaderSettings.)
         [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
         public static XmlReader CreateXmlReader(string filepath)
         {
             if (AppSettings.RestrictXmlControls)
@@ -84,7 +89,9 @@ namespace System.Web.Util {
         }
 
         [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
         public static XmlReader CreateXmlReader(Stream datastream)
         {
             if (AppSettings.RestrictXmlControls)
@@ -100,7 +107,9 @@ namespace System.Web.Util {
         }
 
         [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
         public static XmlReader CreateXmlReader(TextReader reader)
         {
             if (AppSettings.RestrictXmlControls)
@@ -116,7 +125,9 @@ namespace System.Web.Util {
         }
 
         [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
         public static XmlReader CreateXmlReader(Stream contentStream, string baseURI)
         {
             if (AppSettings.RestrictXmlControls)
@@ -179,6 +190,7 @@ namespace System.Web.Util {
 
 #pragma warning disable 0618    // To avoid deprecation warning
         [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         public static XslTransform CreateXslTransform(XmlReader reader)
         {
             if (!AppSettings.RestrictXmlControls)
@@ -191,6 +203,7 @@ namespace System.Web.Util {
         }
 
         [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
         public static XslTransform CreateXslTransform(XmlReader reader, XmlResolver resolver)
         {
             if (!AppSettings.RestrictXmlControls)
index 736c8f48b886d5d6e9cb125268afa88af89d92da..917aeea915482a17b759b5333a3824c2f7f41409 100644 (file)
@@ -232,6 +232,7 @@ namespace System.Web {
 
 
         [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")]
+        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")]
         public override SiteMapNode BuildSiteMap() {
 
             SiteMapNode tempNode = _siteMapNode;
index 5290f57da13591fc7bd51184f48d1e4b2406f361..d1a7668ea7a86cd764262cf9302f5ad6edb0ab7f 100644 (file)
@@ -6,6 +6,7 @@ namespace System.Workflow.ComponentModel.Compiler
     using System.Diagnostics;
     using System.Globalization;
     using System.IO;
+    using System.Xml;
     using System.Text;
     using System.Collections;
     using System.Collections.Specialized;
@@ -1142,7 +1143,7 @@ namespace System.Workflow.ComponentModel.Compiler
                 string name = null;
                 try
                 {
-                    Xml.XmlTextReader reader = new Xml.XmlTextReader(binaryStream);
+                    Xml.XmlTextReader reader = new Xml.XmlTextReader(binaryStream) { DtdProcessing = DtdProcessing.Prohibit };
                     if (reader.MoveToContent() == System.Xml.XmlNodeType.Element)
                     {
                         if (reader.MoveToAttribute("Class", StandardXomlKeys.Definitions_XmlNs))
index 1e658c689b29a22ad02e6e855c46fd046d5e1be4..5488a93ae69fe2b1850e2d8755d8d745fb54b29b 100644 (file)
@@ -193,7 +193,7 @@ namespace System.Workflow.ComponentModel.Design
             {
                 ArrayList objects = new ArrayList();
                 WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(serializationManager);
-                XmlTextReader reader = new XmlTextReader(this.serializedXmlString, XmlNodeType.Element, null);
+                XmlTextReader reader = new XmlTextReader(this.serializedXmlString, XmlNodeType.Element, null) { DtdProcessing = DtdProcessing.Prohibit };
                 reader.MoveToElement();
                 do
                 {
@@ -235,7 +235,7 @@ namespace System.Workflow.ComponentModel.Design
                 xomlSerializationManager.AddSerializationProvider(propertySegmentSerializationProvider);
 
                 StringReader stringReader = new StringReader(this.serializedXmlString);
-                using (XmlTextReader reader = new XmlTextReader(stringReader))
+                using (XmlTextReader reader = new XmlTextReader(stringReader) { DtdProcessing = DtdProcessing.Prohibit })
                 {
                     while (reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.ProcessingInstruction && reader.Read());
 
index 55ef70d7197d8114bb5fbe2302e3111cd2df6464..df277deaef34d2fbc8fd6fe1587ab29f7774a4cb 100644 (file)
@@ -1837,18 +1837,25 @@ namespace System.Workflow.Runtime
             return HashServiceType(serviceType.AssemblyQualifiedName);
         }
 
-        [SuppressMessage("Microsoft.Cryptographic.Standard", "CA5350:MD5CannotBeUsed", 
+        [SuppressMessage("Microsoft.Cryptographic.Standard", "CA5350:MD5CannotBeUsed",
             Justification = "Design has been approved.  We are not using MD5 for any security or cryptography purposes but rather as a hash.")]
         internal static Guid HashServiceType(String serviceFullTypeName)
         {
-            MD5 md5 = new MD5CryptoServiceProvider();
             byte[] data;
             byte[] result;
 
             UnicodeEncoding ue = new UnicodeEncoding();
             data = ue.GetBytes(serviceFullTypeName);
 
-            result = md5.ComputeHash(data);
+            if (AppSettings.FIPSRequired)
+            {
+                result = MD5PInvokeHelper.CalculateHash(data);
+            }
+            else
+            {
+                MD5 md5 = new MD5CryptoServiceProvider();
+                result = md5.ComputeHash(data);
+            }
 
             return new Guid(result);
         }
index 79d95e3450b14547b2f1d1a79b5bdbe1a71d2a0f..7c6905f92bbce017e21c74bbdc6664118f5693f1 100644 (file)
@@ -28,7 +28,8 @@ namespace System.Workflow.Runtime.Tracking
     {
         public TrackingProfileSerializer()
         {
-            _schema = XmlSchema.Read(new StringReader(_xsd), null);
+            StringReader reader = new StringReader(_xsd);
+            _schema = XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
             _schema.Namespaces.Add("", _ns);
         }
 
index 718b7556e48f40a775c6e3efa9722ea81f881a68..1697c085654825b91248d04540723b934d416b38 100644 (file)
@@ -129,6 +129,17 @@ namespace System.Workflow.Runtime
             // listen to activity definition resolve events
             Activity.ActivityResolve += OnActivityDefinitionResolve;
             Activity.WorkflowChangeActionsResolve += OnWorkflowChangeActionsResolve;
+            
+            try
+            {
+                using (TelemetryEventSource eventSource = new TelemetryEventSource())
+                {
+                    eventSource.V1Runtime();
+                }
+            }
+            catch
+            {
+            }
         }
 
         public WorkflowRuntime()
index 8a130a0f34285449d7dc69480eff98e832bf3edd..9224bf8b8fbac5bb40399ab2c13c752e3f0fd57f 100644 (file)
@@ -3,6 +3,15 @@
 //   Copyright (c) Microsoft Corporation.  All rights reserved.
 // 
 // ==--==
+
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 using System;
 using System.Collections.Generic;
 
@@ -167,3 +176,5 @@ namespace System
         static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
     }
 }
+
+#pragma warning restore 436
index f05b599ed3d2b9af36cb7cd29c3c39123370cf6e..33662b54280621d4ef98247f98badecf87773fda 100644 (file)
@@ -4,6 +4,14 @@
 // 
 // ==--==
 
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches
 using System;
 using System.Collections.Generic;
@@ -126,3 +134,5 @@ namespace System
         }
     }
 }
+
+#pragma warning restore 436
index 01ac463e479cb2a8d780ec4a89ef94ccbc7f56bb..ac29b893843139e92f86a303c7a7a25643d0afd0 100644 (file)
@@ -28,6 +28,10 @@ namespace System
                             LocalAppContext.DefineSwitchDefault("Switch.System.Xml.DontThrowOnInvalidSurrogatePairs", true);
                             LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreEmptyKeySequences", true);
                         }
+                        if (version <= 40601)
+                        {
+                            LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreKindInUtcTimeSerialization", true);
+                        }
                         break;
                     }
                 case "WindowsPhone":
@@ -37,6 +41,7 @@ namespace System
                         {
                             LocalAppContext.DefineSwitchDefault("Switch.System.Xml.DontThrowOnInvalidSurrogatePairs", true);
                             LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreEmptyKeySequences", true);
+                            LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreKindInUtcTimeSerialization", true);
                         }
                         break;
                     }
index c744ba1c0dc1f31417a41c6aebe939a34d2da659..ddc3323413220a8f8c2a943b689a7dab9e3748ca 100644 (file)
@@ -29,5 +29,15 @@ namespace System
                 return LocalAppContext.GetCachedSwitchValue(@"Switch.System.Xml.IgnoreEmptyKeySequences", ref _ignoreEmptyKeySequences);
             }
         }
+
+        private static int _ignoreKindInUtcTimeSerialization;
+        public static bool IgnoreKindInUtcTimeSerialization
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return LocalAppContext.GetCachedSwitchValue(@"Switch.System.Xml.IgnoreKindInUtcTimeSerialization", ref _ignoreKindInUtcTimeSerialization);
+            }
+        }
     }
 }
index d186daa2aa52a0656ad5fb8b057411c9b4fcf9df..980381559486698efe6f8851a4d2fc5f222a2160 100644 (file)
@@ -77,7 +77,14 @@ namespace System.Xml.Serialization {
         }
 
         internal static string FromTime(DateTime value) {
-            return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffzzzzzz");
+            if (!LocalAppContextSwitches.IgnoreKindInUtcTimeSerialization && value.Kind == DateTimeKind.Utc)
+            {
+                return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffZ");
+            }
+            else
+            {
+                return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffzzzzzz");
+            }
         }
 
         internal static string FromDateTime(DateTime value) {
@@ -337,7 +344,14 @@ namespace System.Xml.Serialization {
         }
 
         internal static DateTime ToTime(string value) {
-            return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite|DateTimeStyles.AllowTrailingWhite|DateTimeStyles.NoCurrentDateDefault);
+            if (!LocalAppContextSwitches.IgnoreKindInUtcTimeSerialization)
+            {
+                return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.RoundtripKind);
+            }
+            else
+            {
+                return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault);
+            }
         }
 
         internal static char ToChar(string value) {
index 8a130a0f34285449d7dc69480eff98e832bf3edd..9224bf8b8fbac5bb40399ab2c13c752e3f0fd57f 100644 (file)
@@ -3,6 +3,15 @@
 //   Copyright (c) Microsoft Corporation.  All rights reserved.
 // 
 // ==--==
+
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 using System;
 using System.Collections.Generic;
 
@@ -167,3 +176,5 @@ namespace System
         static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
     }
 }
+
+#pragma warning restore 436
index f05b599ed3d2b9af36cb7cd29c3c39123370cf6e..33662b54280621d4ef98247f98badecf87773fda 100644 (file)
@@ -4,6 +4,14 @@
 // 
 // ==--==
 
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches
 using System;
 using System.Collections.Generic;
@@ -126,3 +134,5 @@ namespace System
         }
     }
 }
+
+#pragma warning restore 436
index 872cfa80dd5d3d986d8e5dd89489efb871911649..19ec1053a3a4c9a03682b6d26755c976721b7b3a 100644 (file)
@@ -155,7 +155,14 @@ namespace System
             if (PinnableBufferCacheEventSource.Log.IsEnabled())
                 PinnableBufferCacheEventSource.Log.FreeBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(buffer), buffer.GetHashCode(), m_FreeList.Count);
 
-
+            if(buffer == null)
+            {
+                if (PinnableBufferCacheEventSource.Log.IsEnabled())
+                    PinnableBufferCacheEventSource.Log.FreeBufferNull(m_CacheName, m_FreeList.Count);
+                    
+                return;
+            }
+            
             // After we've done 3 gen1 GCs, assume that all buffers have aged into gen2 on the free path.
             if ((m_gen1CountAtLastRestock + 3) > GC.CollectionCount(GC.MaxGeneration - 1))
             {
@@ -567,6 +574,7 @@ namespace System
         public void AllocateBufferAged(string cacheName, int agedCount) {}
         public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) {}
         public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) {}
+        public void FreeBufferNull(string cacheName, int freeCountBefore) { }
         public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) {}
         public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) {}
         public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) {}
@@ -643,6 +651,8 @@ namespace System
         public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) { if (IsEnabled()) WriteEvent(20, cacheName, promotedToFreeListCount, heldBackCount); }
         [Event(21)]
         public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { if (IsEnabled()) WriteEvent(21, cacheName, freeListCount, gen0BuffersInFreeList); }
+        [Event(22)]
+        public void FreeBufferNull(string cacheName, int freeCountBefore) { if(IsEnabled()) WriteEvent(22, cacheName, freeCountBefore); }
 
 
         static internal ulong AddressOf(object obj)
index a1911293b0db1bc618a3f1e3d217f596c0b4b460..958740229703bc00a6c319db8a9f28f40eb88a0f 100644 (file)
@@ -169,6 +169,23 @@ namespace Microsoft.Win32 {
         [ResourceExposure(ResourceScope.None)]
         public static extern bool WTSUnRegisterSessionNotification(HandleRef hWnd);
 
+        private static IntPtr GetCurrentProcessToken() { return new IntPtr(-4); }
+
+        private const int ERROR_SUCCESS = 0;
+
+        enum AppPolicyClrCompat
+        {
+            AppPolicyClrCompat_Others = 0,
+            AppPolicyClrCompat_ClassicDesktop = 1,
+            AppPolicyClrCompat_Universal = 2,
+            AppPolicyClrCompat_PackagedDesktop = 3
+        };
+
+        [DllImport(ExternDll.Kernel32, CharSet = CharSet.None, EntryPoint = "AppPolicyGetClrCompat")]
+        [System.Security.SecuritySafeCritical]
+        [return: MarshalAs(UnmanagedType.I4)]
+        private static extern Int32 _AppPolicyGetClrCompat(IntPtr processToken, out AppPolicyClrCompat appPolicyClrCompat);
+
         private const int ERROR_INSUFFICIENT_BUFFER = 0x007A;
         private const int ERROR_NO_PACKAGE_IDENTITY = 0x3d54;
 
@@ -204,8 +221,20 @@ namespace Microsoft.Win32 {
         [System.Security.SecuritySafeCritical]
         private static bool _IsPackagedProcess()
         {
+            Version windows8Version = new Version(6, 2, 0, 0);
             OperatingSystem os = Environment.OSVersion;
-            if(os.Platform == PlatformID.Win32NT && os.Version >= new Version(6,2,0,0) && DoesWin32MethodExist(ExternDll.Kernel32, "GetCurrentPackageId"))
+            bool osSupportsPackagedProcesses = os.Platform == PlatformID.Win32NT && os.Version >= windows8Version;
+
+            if (osSupportsPackagedProcesses && DoesWin32MethodExist(ExternDll.Kernel32, "AppPolicyGetClrCompat"))
+            {
+                // Use AppPolicyGetClrCompat if it is available. Return true if and only if this is a UWA which means if
+                // this is packaged desktop app this method will return false. This may cause some confusion however 
+                // this is necessary to make the behavior of packaged desktop apps identical to desktop apps.
+                AppPolicyClrCompat appPolicyClrCompat;
+                return _AppPolicyGetClrCompat(GetCurrentProcessToken(), out appPolicyClrCompat) == ERROR_SUCCESS && 
+                    appPolicyClrCompat == AppPolicyClrCompat.AppPolicyClrCompat_Universal;
+            }
+            else if(osSupportsPackagedProcesses && DoesWin32MethodExist(ExternDll.Kernel32, "GetCurrentPackageId"))
             {
                 Int32 bufLen = 0;
                 // Will return ERROR_INSUFFICIENT_BUFFER when running within a packaged application,
index c16486800a9248e135348c383cee4b20655cc1b4..ebc36a83d4d51ea6f21f6e785cd82773651c8b30 100644 (file)
@@ -326,9 +326,19 @@ namespace System.ComponentModel {
                 return false;
             }
 
-            if ((mdObj.description == null) != (description == null) ||
-                (description != null && !mdObj.category.Equals(description))) {
-                return false;
+            // VSO 149471 - Technically fixing this could cause a behavior change, so we are
+            // adding a quirk in case anyone is bit by this and needs the old, buggy behavior.
+            if (!LocalAppContextSwitches.MemberDescriptorEqualsReturnsFalseIfEquivalent) {
+                if ((mdObj.description == null) != (description == null) ||
+                    (description != null && !mdObj.description.Equals(description))) {
+                    return false;
+                }
+            }
+            else {
+                if ((mdObj.description == null) != (description == null) ||
+                    (description != null && !mdObj.category.Equals(description))) {
+                    return false;
+                }
             }
 
             if ((mdObj.attributes == null) != (attributes == null)) {
index 320e1d69ff4308f8f34d1d71128d78b0226531ea..a789a6ea2be1399a712e3246532eeae7d7ff0e65 100644 (file)
@@ -300,6 +300,9 @@ namespace System.Net {
             }
         }
 
+        // Note: RequestBuffer may get moved in memory. If you dereference a pointer from inside the RequestBuffer, 
+        // you must use 'OriginalBlobAddress' below to adjust the location of the pointer to match the location of
+        // RequestBuffer.
         internal byte[] RequestBuffer
         {
             get
@@ -1061,7 +1064,7 @@ namespace System.Net {
 
             m_TokenBindings = new List<TokenBinding>();
 
-            UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO* pTokenBindingInfo = GetTlsTokenBindingRequestInfo();
+            UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO* pTokenBindingInfo = UnsafeNclNativeMethods.HttpApi.GetTlsTokenBindingRequestInfo(RequestBuffer, OriginalBlobAddress);
 
             if (pTokenBindingInfo == null)
             {
@@ -1116,23 +1119,6 @@ namespace System.Net {
             }
         }
 
-        private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO* GetTlsTokenBindingRequestInfo() {
-            fixed (byte* pMemoryBlob = RequestBuffer)
-            {
-                UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2* request = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)pMemoryBlob;
-
-                for (int i = 0; i < request->RequestInfoCount; i++)
-                {
-                    UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO* pThisInfo = &request->pRequestInfo[i];
-                    if (pThisInfo != null && pThisInfo->InfoType == UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslTokenBinding)
-                    {
-                        return (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO*)pThisInfo->pInfo;
-                    }
-                }
-            }
-            return null;
-        }
-
         internal void CheckDisposed() {
             if (m_IsDisposed) {
                 throw new ObjectDisposedException(this.GetType().FullName);
index d04932e503f93d4c7f85e75d50d3d4f9e90c20b7..05732c28d3646eba263c003145863812cd75f45d 100644 (file)
@@ -1406,6 +1406,7 @@ typedef struct _SCHANNEL_CRED
             ValidateManual  = 0x08,
             NoDefaultCred   = 0x10,
             ValidateAuto    = 0x20,
+            SendAuxRecord   = 0x00200000,
             UseStrongCrypto = 0x00400000,
         }
 
index 01776e420decae36178b835e2d0e9a83bc95adb8..b5488d4a2992ed3043c70817ed1dcb28f1ea0673 100644 (file)
@@ -592,9 +592,17 @@ namespace System.Net.Security {
                         KeyExchangeStrength));
                 }
             }
+            catch (Exception)
+            {
+                // If an exception emerges synchronously, the asynchronous operation was not
+                // initiated, so no operation is in progress.
+                _NestedAuth = 0;
+                
+                throw;
+            }
             finally
             {
-                if (lazyResult == null || _Exception != null)
+                if (lazyResult == null)
                 {
                     _NestedAuth = 0;
                 }
index 48bb45802f08f94ea2fef8a6beeb4683a85450e6..3de63c914d6398d3bf378050c4e94d43972700c9 100644 (file)
@@ -247,12 +247,15 @@ namespace System.Net {
         private static volatile CertPolicyValidationCallback s_CertPolicyValidationCallback = new CertPolicyValidationCallback();
         private static volatile ServerCertValidationCallback s_ServerCertValidationCallback = null;
 
+        private const string sendAuxRecordValueName = "SchSendAuxRecord";
+        private const string sendAuxRecordAppSetting = "System.Net.ServicePointManager.SchSendAuxRecord";
         private const string strongCryptoValueName = "SchUseStrongCrypto";
         private const string secureProtocolAppSetting = "System.Net.ServicePointManager.SecurityProtocol";
 
-        private static object disableStrongCryptoLock = new object();
-        private static volatile bool disableStrongCryptoInitialized = false;
+        private static object configurationLoadedLock = new object();
+        private static volatile bool configurationLoaded = false;
         private static bool disableStrongCrypto = false;
+        private static bool disableSendAuxRecord = false;
 
         private static SecurityProtocolType s_SecurityProtocolType = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
 
@@ -427,11 +430,11 @@ namespace System.Net {
         [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety")]
         public static SecurityProtocolType SecurityProtocol {
             get {
-                EnsureStrongCryptoSettingsInitialized();
+                EnsureConfigurationLoaded();
                 return s_SecurityProtocolType;
             }
             set {
-                EnsureStrongCryptoSettingsInitialized();
+                EnsureConfigurationLoaded();
                 ValidateSecurityProtocol(value);
                 s_SecurityProtocolType = value;
             }
@@ -640,77 +643,118 @@ namespace System.Net {
 
         internal static bool DisableStrongCrypto {
             get {
-                EnsureStrongCryptoSettingsInitialized();
-                return (bool)disableStrongCrypto; 
+                EnsureConfigurationLoaded();
+                return disableStrongCrypto; 
             }
         }
 
-        private static void EnsureStrongCryptoSettingsInitialized() {
-            
-            if (disableStrongCryptoInitialized) {
+        internal static bool DisableSendAuxRecord {
+            get {
+                EnsureConfigurationLoaded();
+                return disableSendAuxRecord;
+            }
+        }
+
+        private static void EnsureConfigurationLoaded() {
+            if (configurationLoaded) {
                 return;
             }
 
-            lock (disableStrongCryptoLock) {
-                if (disableStrongCryptoInitialized) {
+            lock (configurationLoadedLock) {
+                if (configurationLoaded) {
                     return;
                 }
 
-                try {
-                    bool disableStrongCryptoInternal = false;
-                    int schUseStrongCryptoKeyValue = 0;
+                LoadDisableStrongCryptoConfiguration();
+                LoadDisableSendAuxRecordConfiguration();
 
-                    if (LocalAppContextSwitches.DontEnableSchUseStrongCrypto)
-                    {
-                        //.Net 4.5.2 and below will default to false unless the registry key is specifically set to 1.
-                        schUseStrongCryptoKeyValue =
-                            RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 0);
+                configurationLoaded = true;
+            }
+        }
 
-                        disableStrongCryptoInternal = schUseStrongCryptoKeyValue != 1;
-                    }
-                    else
-                    {
-                        // .Net 4.6 and above will default to true unless the registry key is specifically set to 0.
-                        schUseStrongCryptoKeyValue = 
-                            RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 1);
+        private static void LoadDisableStrongCryptoConfiguration() {
+            try {
+                bool disableStrongCryptoInternal = false;
+                int schUseStrongCryptoKeyValue = 0;
 
-                        disableStrongCryptoInternal = schUseStrongCryptoKeyValue == 0;
-                    }
-                    
-                    if (disableStrongCryptoInternal) {
-                        // Revert the SecurityProtocol selection to the legacy combination.
-                        s_SecurityProtocolType = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
-                    }
-                    else {
-                        s_SecurityProtocolType =
-                            SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
+                if (LocalAppContextSwitches.DontEnableSchUseStrongCrypto) {
+                    //.Net 4.5.2 and below will default to false unless the registry key is specifically set to 1.
+                    schUseStrongCryptoKeyValue =
+                        RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 0);
 
-                        string appSetting = RegistryConfiguration.AppConfigReadString(secureProtocolAppSetting, null);
+                    disableStrongCryptoInternal = schUseStrongCryptoKeyValue != 1;
+                }
+                else {
+                    // .Net 4.6 and above will default to true unless the registry key is specifically set to 0.
+                    schUseStrongCryptoKeyValue =
+                        RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 1);
 
-                        SecurityProtocolType value;
-                        try {
-                            value = (SecurityProtocolType)Enum.Parse(typeof(SecurityProtocolType), appSetting);
-                            ValidateSecurityProtocol(value);
-                            s_SecurityProtocolType = value;
-                        }
-                        // Ignore all potential exceptions caused by Enum.Parse.
-                        catch (ArgumentNullException) { }
-                        catch (ArgumentException) { }
-                        catch (NotSupportedException) { }
-                        catch (OverflowException) { }
-                    }
+                    disableStrongCryptoInternal = schUseStrongCryptoKeyValue == 0;
+                }
 
-                    disableStrongCrypto = disableStrongCryptoInternal;
-                    disableStrongCryptoInitialized = true;
+                if (disableStrongCryptoInternal) {
+                    // Revert the SecurityProtocol selection to the legacy combination.
+                    s_SecurityProtocolType = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
                 }
-                catch (Exception e) {
-                    if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
-                        throw;
+                else {
+                    s_SecurityProtocolType =
+                        SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
+
+                    string appSetting = RegistryConfiguration.AppConfigReadString(secureProtocolAppSetting, null);
+
+                    SecurityProtocolType value;
+                    try {
+                        value = (SecurityProtocolType)Enum.Parse(typeof(SecurityProtocolType), appSetting);
+                        ValidateSecurityProtocol(value);
+                        s_SecurityProtocolType = value;
                     }
+                    // Ignore all potential exceptions caused by Enum.Parse.
+                    catch (ArgumentNullException) { }
+                    catch (ArgumentException) { }
+                    catch (NotSupportedException) { }
+                    catch (OverflowException) { }
+                }
+
+                disableStrongCrypto = disableStrongCryptoInternal;
+            }
+            catch (Exception e)
+            {
+                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
+                {
+                    throw;
                 }
             }
         }
-        
+
+        private static void LoadDisableSendAuxRecordConfiguration() {
+            try { 
+                if (LocalAppContextSwitches.DontEnableSchSendAuxRecord) {
+                    disableSendAuxRecord = true;
+                    return;
+                }
+
+                int schSendAuxRecordKeyValue = 1;
+                schSendAuxRecordKeyValue = RegistryConfiguration.AppConfigReadInt(sendAuxRecordAppSetting, 1);
+                if (schSendAuxRecordKeyValue == 0) {
+                    disableSendAuxRecord = true;
+                    return;
+                }
+            
+                schSendAuxRecordKeyValue = RegistryConfiguration.GlobalConfigReadInt(sendAuxRecordValueName, 1);
+                if (schSendAuxRecordKeyValue == 0) {
+                    disableSendAuxRecord = true;
+                    return;
+                }
+            }
+            catch (Exception e)
+            {
+                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
+                {
+                    throw;
+                }
+            }
+        }
+
         public static bool ReusePort {
             get {
                 EnsureReusePortSettingsInitialized();
index 7cf970ed013f48125de2c07a4a866a49c4cbd648..680ea9813968ee030704b14352a20cc2eaaede54 100644 (file)
@@ -1482,7 +1482,7 @@ namespace System.Net {
                                                 [Out] out int bytesTransferred,
                                                 [In]  SafeHandle overlapped,
                                                 [In]  IntPtr completionRoutine
-                                                );                     
+                                                );                 
 
             [DllImport(WS2_32,SetLastError=true)]
             internal static extern SocketError WSAEnumNetworkEvents(
@@ -3147,6 +3147,25 @@ namespace System.Net {
                 GlobalLog.Leave("HttpApi::GetLocalEndPoint()");
                 return endpoint;
             }
+            
+            internal static HTTP_REQUEST_TOKEN_BINDING_INFO* GetTlsTokenBindingRequestInfo(byte[] memoryBlob, IntPtr originalAddress){
+                
+                fixed (byte* pMemoryBlob = memoryBlob)
+                {
+                    HTTP_REQUEST_V2* request = (HTTP_REQUEST_V2*)pMemoryBlob;                    
+                    long fixup = pMemoryBlob - (byte*) originalAddress;
+
+                    for (int i = 0; i < request->RequestInfoCount; i++)
+                    {
+                        HTTP_REQUEST_INFO* pThisInfo = (HTTP_REQUEST_INFO*)(fixup + (byte*)&request->pRequestInfo[i]);
+                        if (pThisInfo != null && pThisInfo->InfoType == HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslTokenBinding)
+                        {
+                            return (HTTP_REQUEST_TOKEN_BINDING_INFO*)pThisInfo->pInfo;
+                        }
+                    }
+                }
+                return null;
+            }
 
             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
             private static void CopyOutAddress(IntPtr address, ref SocketAddress v4address, ref SocketAddress v6address)
index 9f04a33e0b7d529739ef11c801bfd54f017b75bc..58400b2b26f17a861b660ac1c0b5c356e60c05cb 100644 (file)
@@ -393,7 +393,7 @@ namespace System.Net.Security {
                 if (store != null)
                 {
                     collectionEx = store.Certificates.Find(X509FindType.FindByThumbprint, certHash, false);
-                    if (collectionEx.Count > 0 && collectionEx[0].PrivateKey != null)
+                    if (collectionEx.Count > 0 && collectionEx[0].HasPrivateKey)
                     {
                         if (Logging.On) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_found_cert_in_store, (m_ServerMode ? "LocalMachine" : "CurrentUser")));
                         return collectionEx[0];
@@ -404,7 +404,7 @@ namespace System.Net.Security {
                 if (store != null)
                 {
                     collectionEx = store.Certificates.Find(X509FindType.FindByThumbprint, certHash, false);
-                    if (collectionEx.Count > 0 && collectionEx[0].PrivateKey != null)
+                    if (collectionEx.Count > 0 && collectionEx[0].HasPrivateKey)
                     {
                         if (Logging.On) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_found_cert_in_store, (m_ServerMode ? "CurrentUser" : "LocalMachine")));
                         return collectionEx[0];
@@ -791,6 +791,12 @@ namespace System.Net.Security {
                 else
                 {
                     SecureCredential.Flags flags = SecureCredential.Flags.ValidateManual | SecureCredential.Flags.NoDefaultCred;
+
+                    if (!ServicePointManager.DisableSendAuxRecord)
+                    {
+                        flags |= SecureCredential.Flags.SendAuxRecord;
+                    }
+
                     if (!ServicePointManager.DisableStrongCrypto 
                         && ((m_ProtocolFlags & (SchProtocols.Tls10 | SchProtocols.Tls11 | SchProtocols.Tls12)) != 0)
                         && (m_EncryptionPolicy != EncryptionPolicy.AllowNoEncryption) && (m_EncryptionPolicy != EncryptionPolicy.NoEncryption))
@@ -876,7 +882,14 @@ namespace System.Net.Security {
                 }
                 else
                 {
-                    SecureCredential secureCredential = new SecureCredential(SecureCredential.CurrentVersion, selectedCert, SecureCredential.Flags.Zero, m_ProtocolFlags, m_EncryptionPolicy);
+                    SecureCredential.Flags flags = SecureCredential.Flags.Zero;
+
+                    if (!ServicePointManager.DisableSendAuxRecord)
+                    {
+                        flags |= SecureCredential.Flags.SendAuxRecord;
+                    }
+
+                    SecureCredential secureCredential = new SecureCredential(SecureCredential.CurrentVersion, selectedCert, flags, m_ProtocolFlags, m_EncryptionPolicy);
                     m_CredentialsHandle = AcquireCredentialsHandle(CredentialUse.Inbound, ref secureCredential);
                     thumbPrint = guessedThumbPrint;
                     m_ServerCertificate = localCertificate;
index 39d0c2c0f6c98c5b6b90f7cda523ad1aa6fe7306..cbe1ea3f7085c8538d3b7d59150fe554c594cb9b 100644 (file)
@@ -55,13 +55,6 @@ namespace System {
             if (start==end)
                 return false;
 
-#if MONO
-            if (!Uri.IsWindowsFileSystem) {
-                if (!(end - start > 2 && name[start] == '\\' && name[start + 1] == '\\')) {
-                    return false;
-                }
-            }
-#endif
             //
             // First segment could consist of only '_' or '-' but it cannot be all digits or empty
             //
index ed0965d382f9dd468f2e720fbca5945310a5fcf6..500280aed332b4aceaec2b94e3e7babe19480585 100644 (file)
@@ -586,9 +586,6 @@ namespace System.IO {
                             }
                             else {
                                 if (oldName != null) {
-                                    Debug.Assert(false, "FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" +
-                                                                  "new name!  [" + oldName + "]");
-    
                                     NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
                                     oldName = null;
                                 }
index a084bb5dc8e7dacc7d3b7f8452cecff8bc0e8729..da13e1930260edaf90b2bfe15081785db4edd065 100644 (file)
@@ -27,6 +27,11 @@ namespace System
                         {
                             LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true);
                         }
+
+                        if (version <= 40601)
+                        {
+                            LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.MemberDescriptorEqualsReturnsFalseIfEquivalentName, true);
+                        }
                         break;
                     }
                 case "WindowsPhone":
@@ -34,7 +39,7 @@ namespace System
                     {
                         if (version <= 80100)
                         {
-                            LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true);
+                             LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true);
                         }
                         break;
                     }
index 50f2bac56df83f542b4d276a85de675f7c5346f5..0d28af1593f7fcbfc84d9dfce2fe6f21369ac349 100644 (file)
@@ -11,7 +11,21 @@ namespace System
     internal static class LocalAppContextSwitches
     {
 
-#region System.Net quirks
+        #region System quirks
+        private static int _memberDescriptorEqualsReturnsFalseIfEquivalent;
+        internal const string MemberDescriptorEqualsReturnsFalseIfEquivalentName = @"Switch.System.MemberDescriptorEqualsReturnsFalseIfEquivalent";
+
+        public static bool MemberDescriptorEqualsReturnsFalseIfEquivalent
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return LocalAppContext.GetCachedSwitchValue(MemberDescriptorEqualsReturnsFalseIfEquivalentName, ref _memberDescriptorEqualsReturnsFalseIfEquivalent);
+            }
+        }
+        #endregion
+
+        #region System.Net quirks
         private static int _dontEnableSchUseStrongCrypto;
         internal const string DontEnableSchUseStrongCryptoName = @"Switch.System.Net.DontEnableSchUseStrongCrypto";
 
@@ -23,9 +37,7 @@ namespace System
                 return LocalAppContext.GetCachedSwitchValue(DontEnableSchUseStrongCryptoName, ref _dontEnableSchUseStrongCrypto);
             }
         }
-#endregion
 
-#region System.Net.WebSockets.HttpListenerAsyncEventArgs
         private static int _allocateOverlappedOnDemand;
         internal const string AllocateOverlappedOnDemandName = @"Switch.System.Net.WebSockets.HttpListenerAsyncEventArgs.AllocateOverlappedOnDemand";
 
@@ -37,7 +49,18 @@ namespace System
                 return LocalAppContext.GetCachedSwitchValue(AllocateOverlappedOnDemandName, ref _allocateOverlappedOnDemand);
             }
         }
-#endregion
 
+        private static int _dontEnableSchSendAuxRecord;
+        internal const string DontEnableSchSendAuxRecordName = @"Switch.System.Net.DontEnableSchSendAuxRecord";
+
+        public static bool DontEnableSchSendAuxRecord
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return LocalAppContext.GetCachedSwitchValue(DontEnableSchSendAuxRecordName, ref _dontEnableSchSendAuxRecord);
+            }
+        }
+        #endregion
     }
 }
index 30a681e707b8368e1c31632de420949154b1c12e..fb57cc3cbaa1977443e351250df829b1ad6efd28 100644 (file)
@@ -198,8 +198,11 @@ namespace Microsoft.Build.Tasks.Xaml
                     }
                     else
                     {
-                        AppDomain.Unload(inProcessAppDomain);
-                        inProcessAppDomain = null;
+                        if (inProcessAppDomain != null)
+                        {
+                            AppDomain.Unload(inProcessAppDomain);
+                            inProcessAppDomain = null;
+                        }
                         return GetAppDomainAndExecute();
                     }
                 }
index 03a90fba66abaff704862fa9e17052fdbbc040a4..a21ac391e5e4be15fde7e692d9fd2efb540c2b3d 100644 (file)
@@ -215,6 +215,12 @@ namespace Microsoft.Build.Tasks.Xaml
             appDomainSetup.ApplicationBase = buildTaskPath;
             appDomainSetup.LoaderOptimization = LoaderOptimization.MultiDomainHost;
 
+            // Set the AppDomainManager class name and assembly name to the empty string. We don't want the AppDomain to try to load the
+            // Microsoft.VisualStudio.Platform.AppDomainManager.dll because it is no longer in the GAC, so it won't be found
+            // by the AppDomain that is created for the in-process build to support Intellisense in Visual Studio.
+            appDomainSetup.AppDomainManagerType = "";
+            appDomainSetup.AppDomainManagerAssembly = "";
+
             // Create appdomain with fulltrust.
             return AppDomain.CreateDomain(
                 friendlyName,
index 872cfa80dd5d3d986d8e5dd89489efb871911649..19ec1053a3a4c9a03682b6d26755c976721b7b3a 100644 (file)
@@ -155,7 +155,14 @@ namespace System
             if (PinnableBufferCacheEventSource.Log.IsEnabled())
                 PinnableBufferCacheEventSource.Log.FreeBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(buffer), buffer.GetHashCode(), m_FreeList.Count);
 
-
+            if(buffer == null)
+            {
+                if (PinnableBufferCacheEventSource.Log.IsEnabled())
+                    PinnableBufferCacheEventSource.Log.FreeBufferNull(m_CacheName, m_FreeList.Count);
+                    
+                return;
+            }
+            
             // After we've done 3 gen1 GCs, assume that all buffers have aged into gen2 on the free path.
             if ((m_gen1CountAtLastRestock + 3) > GC.CollectionCount(GC.MaxGeneration - 1))
             {
@@ -567,6 +574,7 @@ namespace System
         public void AllocateBufferAged(string cacheName, int agedCount) {}
         public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) {}
         public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) {}
+        public void FreeBufferNull(string cacheName, int freeCountBefore) { }
         public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) {}
         public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) {}
         public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) {}
@@ -643,6 +651,8 @@ namespace System
         public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) { if (IsEnabled()) WriteEvent(20, cacheName, promotedToFreeListCount, heldBackCount); }
         [Event(21)]
         public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { if (IsEnabled()) WriteEvent(21, cacheName, freeListCount, gen0BuffersInFreeList); }
+        [Event(22)]
+        public void FreeBufferNull(string cacheName, int freeCountBefore) { if(IsEnabled()) WriteEvent(22, cacheName, freeCountBefore); }
 
 
         static internal ulong AddressOf(object obj)
index 9c2df18a2daf5d191612169f1bcc5d0cb9f10b82..1bf3586fe471a184fd2979557e4ed976454224d7 100644 (file)
@@ -937,6 +937,10 @@ namespace Microsoft.Win32 {
         [ResourceExposure(ResourceScope.Machine)]
         internal unsafe static extern int GetFullPathName(char* path, int numBufferChars, char* buffer, IntPtr mustBeZero);
 
+        [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
+        [ResourceExposure(ResourceScope.Machine)]
+        internal unsafe static extern uint GetFullPathNameW(char* path, uint numBufferChars, SafeHandle buffer, IntPtr mustBeZero);
+
         [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
         [ResourceExposure(ResourceScope.Machine)]
         internal unsafe static extern int GetFullPathName(String path, int numBufferChars, [Out]StringBuilder buffer, IntPtr mustBeZero);
@@ -949,6 +953,14 @@ namespace Microsoft.Win32 {
         [ResourceExposure(ResourceScope.Machine)]
         internal static extern int GetLongPathName(String path, [Out]StringBuilder longPathBuffer, int bufferLength);
 
+        [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
+        [ResourceExposure(ResourceScope.Machine)]
+        internal static extern uint GetLongPathNameW(SafeHandle lpszShortPath, SafeHandle lpszLongPath, uint cchBuffer);
+
+        [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
+        [ResourceExposure(ResourceScope.Machine)]
+        internal static extern uint GetLongPathNameW(string lpszShortPath, SafeHandle lpszLongPath, uint cchBuffer);
+
         // Disallow access to all non-file devices from methods that take
         // a String.  This disallows DOS devices like "con:", "com1:", 
         // "lpt1:", etc.  Use this to avoid security problems, like allowing
@@ -1397,6 +1409,10 @@ namespace Microsoft.Win32 {
                   int nBufferLength,
                   [Out]StringBuilder lpBuffer);
 
+        [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
+        [ResourceExposure(ResourceScope.Machine)]
+        internal static extern uint GetCurrentDirectoryW(uint nBufferLength, SafeHandle lpBuffer);
+
         [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
         [ResourceExposure(ResourceScope.None)]
         internal static extern bool GetFileAttributesEx(String name, int fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation);
index 0b00ff218213342fde4a54bb478ce88443725390..fe0253ba38cb1dac7dddb2d0a6476c8a59b269a4 100644 (file)
@@ -18,8 +18,7 @@ namespace System
             HasLookedForOverride = 0x4,
             UnknownValue = 0x8 // Has no default and could not find an override
         }
-        private static Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
-        private static readonly object s_syncLock = new object();
+        private static readonly Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
 
         public static string BaseDirectory
         {
@@ -151,11 +150,12 @@ namespace System
             if (switchName.Length == 0)
                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName");
 
-            lock (s_syncLock)
+            SwitchValueState switchValue = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
+                                             | SwitchValueState.HasLookedForOverride;
+            lock (s_switchMap)
             {
                 // Store the new value and the fact that we checked in the dictionary
-                s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
-                                            | SwitchValueState.HasLookedForOverride;
+                s_switchMap[switchName] = switchValue;
             }
         }
 
index bc1f347abb00a2a714daf704abe8b592aac73196..d934f6ac188b3d09339395bc2db2b2b5e2a68fca 100644 (file)
@@ -1,4 +1,4 @@
-// ==++==
+// ==++==
 // 
 //   Copyright (c) Microsoft Corporation.  All rights reserved.
 // 
@@ -13,8 +13,11 @@ namespace System
         internal static readonly string SwitchNoAsyncCurrentCulture = "Switch.System.Globalization.NoAsyncCurrentCulture";
         internal static readonly string SwitchThrowExceptionIfDisposedCancellationTokenSource = "Switch.System.Threading.ThrowExceptionIfDisposedCancellationTokenSource";
         internal static readonly string SwitchPreserveEventListnerObjectIdentity = "Switch.System.Diagnostics.EventSource.PreserveEventListnerObjectIdentity";
+        internal static readonly string SwitchUseLegacyPathHandling = "Switch.System.IO.UseLegacyPathHandling";
+        internal static readonly string SwitchBlockLongPaths = "Switch.System.IO.BlockLongPaths";
+        internal static readonly string SwitchSetActorAsReferenceWhenCopyingClaimsIdentity = "Switch.System.Security.ClaimsIdentity.SetActorAsReferenceWhenCopyingClaimsIdentity";
+
 
-        
         // This is a partial method. Platforms can provide an implementation of it that will set override values
         // from whatever mechanism is available on that platform. If no implementation is provided, the compiler is going to remove the calls
         // to it from the code
@@ -41,6 +44,14 @@ namespace System
                             AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
                             AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
                         }
+
+                        if (version <= 40601)
+                        {
+                            AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true);
+                            AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true);
+                            AppContext.DefineSwitchDefault(SwitchSetActorAsReferenceWhenCopyingClaimsIdentity, true);
+                        }
+
                         break;
                     }
                 case "WindowsPhone":
@@ -50,6 +61,8 @@ namespace System
                         {
                             AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
                             AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
+                            AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true);
+                            AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true);
                         }
                         break;
                     }
index 8a130a0f34285449d7dc69480eff98e832bf3edd..9224bf8b8fbac5bb40399ab2c13c752e3f0fd57f 100644 (file)
@@ -3,6 +3,15 @@
 //   Copyright (c) Microsoft Corporation.  All rights reserved.
 // 
 // ==--==
+
+// There are cases where we have multiple assemblies that are going to import this file and 
+// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
+// that the type is found both in the source and in a referenced assembly. The compiler will prefer 
+// the version of the type defined in the source
+//
+// In order to disable the warning for this type we are disabling this warning for this entire file.
+#pragma warning disable 436
+
 using System;
 using System.Collections.Generic;
 
@@ -167,3 +176,5 @@ namespace System
         static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
     }
 }
+
+#pragma warning restore 436
index 539e877016dc42f39a5e2ec291e99421159d6627..72eb1cccb11adbe47978c594e96df8d78eb5563f 100644 (file)
@@ -41,6 +41,48 @@ namespace System
             }
         }
 
+        private static int _useLegacyPathHandling;
+
+        /// <summary>
+        /// Use legacy path normalization logic and blocking of extended syntax.
+        /// </summary>
+        public static bool UseLegacyPathHandling
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return GetCachedSwitchValue(AppContextDefaultValues.SwitchUseLegacyPathHandling, ref _useLegacyPathHandling);
+            }
+        }
+
+        private static int _blockLongPaths;
+
+        /// <summary>
+        /// Throw PathTooLongException for paths greater than MAX_PATH or directories greater than 248 (as per CreateDirectory Win32 limitations)
+        /// </summary>
+        public static bool BlockLongPaths
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return GetCachedSwitchValue(AppContextDefaultValues.SwitchBlockLongPaths, ref _blockLongPaths);
+            }
+        }
+
+        private static int _cloneActor;
+
+        /// <summary>
+        /// When copying a ClaimsIdentity.Actor this switch controls whether ClaimsIdentity.Actor should be set as a reference or the result of Actor.Clone()
+        /// </summary>
+        public static bool SetActorAsReferenceWhenCopyingClaimsIdentity
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return GetCachedSwitchValue(AppContextDefaultValues.SwitchSetActorAsReferenceWhenCopyingClaimsIdentity, ref _cloneActor);
+            }
+        }
+
         //
         // Implementation details
         //
index fb850445ce344c48b703979b209323a92f7f829c..5509b40250328c80a4b1bcdbb3a1cbc07781bfab 100644 (file)
@@ -318,17 +318,23 @@ namespace System {
             }
         }
 
-        [ResourceExposure(ResourceScope.Machine)]
-        [ResourceConsumption(ResourceScope.Machine)]
-        private String NormalizePath(String path, bool useAppBase)
+        [System.Security.SecuritySafeCritical]
+        private string NormalizePath(string path, bool useAppBase)
         {
             if(path == null)
                 return null;
 
             // If we add very long file name support ("\\?\") to the Path class then this is unnecesary,
             // but we do not plan on doing this for now.
+
+            // Long path checks can be quirked, and as loading default quirks too early in the setup of an AppDomain is risky
+            // we'll avoid checking path lengths- we'll still fail at MAX_PATH later if we're !useAppBase when we call Path's
+            // NormalizePath.
             if (!useAppBase)
-                path = System.Security.Util.URLString.PreProcessForExtendedPathRemoval(path, false);
+                path = System.Security.Util.URLString.PreProcessForExtendedPathRemoval(
+                    checkPathLength: false,
+                    url: path,
+                    isFileUrl: false);
 
             int len = path.Length;
             if (len == 0)
@@ -417,10 +423,10 @@ namespace System {
 
             if (localPath) 
             {
-
                 if (useAppBase &&
-                    ( (len == 1) || (path[1] != ':') )) {
-                    String appBase = Value[(int) LoaderInformation.ApplicationBaseValue];
+                    ((len == 1) || (path[1] != ':'))) 
+                {
+                    String appBase = Value[(int)LoaderInformation.ApplicationBaseValue];
 
                     if ((appBase == null) || (appBase.Length == 0))
                         throw new MemberAccessException(Environment.GetResourceString("AppDomain_AppBaseNotSet"));
@@ -429,7 +435,9 @@ namespace System {
 
                     bool slash = false;
                     if ((path[0] == '/') || (path[0] == '\\')) {
-                        String pathRoot = Path.GetPathRoot(appBase);
+                        // Emulate Path.GetPathRoot without hitting code paths that check quirks
+                        string pathRoot = AppDomain.NormalizePath(appBase, fullCheck: false);
+                        pathRoot = pathRoot.Substring(0, System.IO.PathInternal.GetRootLength(pathRoot));
                         if (pathRoot.Length == 0) { // URL
                             int index = appBase.IndexOf(":/", StringComparison.Ordinal);
                             if (index == -1)
@@ -439,11 +447,11 @@ namespace System {
                             int urlLen = appBase.Length;
                             for (index += 1;
                                  (index < urlLen) && ((appBase[index] == '/') || (appBase[index] == '\\'));
-                                 index++);
+                                 index++) ;
 
                             // Now find the next slash to get domain name
-                            for(; (index < urlLen) && (appBase[index] != '/') && (appBase[index] != '\\');
-                                index++);
+                            for (; (index < urlLen) && (appBase[index] != '/') && (appBase[index] != '\\');
+                                index++) ;
 
                             pathRoot = appBase.Substring(0, index);
                         }
@@ -472,7 +480,9 @@ namespace System {
                     path = StringBuilderCache.GetStringAndRelease(result);
                 }
                 else
-                    path = Path.GetFullPathInternal(path);
+                {
+                    path = AppDomain.NormalizePath(path, fullCheck: true);
+                }
             }
 
             return path;
@@ -792,20 +802,32 @@ namespace System {
         [ResourceConsumption(ResourceScope.Machine)]
         private String VerifyDir(String dir, bool normalize)
         {
-            if (dir != null) {
+            if (dir != null)
+            {
                 if (dir.Length == 0)
+                {
                     dir = null;
-                else {
+                }
+                else
+                {
                     if (normalize)
                         dir = NormalizePath(dir, true);
 
-                // The only way AppDomainSetup is exposed in coreclr is through the AppDomainManager 
-                // and the AppDomainManager is a SecurityCritical type. Also, all callers of callstacks 
-                // leading from VerifyDir are SecurityCritical. So we can remove the Demand because 
-                // we have validated that all callers are SecurityCritical
+                    // The only way AppDomainSetup is exposed in coreclr is through the AppDomainManager 
+                    // and the AppDomainManager is a SecurityCritical type. Also, all callers of callstacks 
+                    // leading from VerifyDir are SecurityCritical. So we can remove the Demand because 
+                    // we have validated that all callers are SecurityCritical
 #if !FEATURE_CORECLR
                     if (IsFilePath(dir))
-                        new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dir ).Demand();
+                    {
+                        // If we've already normalized we don't need to do it again, and can avoid hitting
+                        // quirks in FileIOPermission.
+                        new FileIOPermission(
+                            access: FileIOPermissionAccess.PathDiscovery,
+                            pathList: new string[] { dir },
+                            checkForDuplicates: false,
+                            needFullPath: false).Demand();
+                    }
 #endif // !FEATURE_CORECLR
                 }
             }
index 0d7719d224a5cc564d4059a538c91201946c6082..2a704e83006fa15410f41e5e15bbe8ae7ddd0a4f 100644 (file)
@@ -2712,7 +2712,7 @@ namespace System {
             get {
                 String dyndir = GetDynamicDir();
                 if (dyndir != null)
-                    new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dyndir ).Demand();
+                    FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, dyndir);
 
                 return dyndir;
             }
@@ -3726,7 +3726,7 @@ namespace System {
             AppDomainInitializerInfo initializerInfo    = (AppDomainInitializerInfo)args[5];
             string           sandboxName                = (string)args[6];
             string[]         propertyNames              = (string[])args[7]; // can contain null elements
-            string[]         propertyValues             = (string[])args[8]; // can contain null elements           
+            string[]         propertyValues             = (string[])args[8]; // can contain null elements
             // extract evidence
             Evidence providedSecurityInfo = null;
             Evidence creatorsSecurityInfo = null;
@@ -3748,18 +3748,17 @@ namespace System {
                         if (Path.IsRelative(propertyValues[i]))
                             throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
 
-                        newSetup.ApplicationBase=Path.NormalizePath(propertyValues[i],true);
-
+                        newSetup.ApplicationBase = NormalizePath(propertyValues[i], fullCheck: true);
                     }
 #if FEATURE_CAS_POLICY
                     else if(propertyNames[i]=="LOCATION_URI" && providedSecurityInfo==null)
                     {
                         providedSecurityInfo=new Evidence();
                         providedSecurityInfo.AddHostEvidence(new Url(propertyValues[i]));
-                        ad.SetDataHelper(propertyNames[i],propertyValues[i],null);                        
+                        ad.SetDataHelper(propertyNames[i],propertyValues[i],null);
                     }
 #endif // FEATURE_CAS_POLICY
-#if FEATURE_LOADER_OPTIMIZATION                    
+#if FEATURE_LOADER_OPTIMIZATION
                     else
                     if(propertyNames[i]=="LOADER_OPTIMIZATION")
                     {
@@ -3775,8 +3774,8 @@ namespace System {
                             default: throw new ArgumentException(Environment.GetResourceString("Argument_UnrecognizedLoaderOptimization"), "LOADER_OPTIMIZATION");
                         }
                     }
-#endif // FEATURE_LOADER_OPTIMIZATION                    
-#if FEATURE_CORECLR      
+#endif // FEATURE_LOADER_OPTIMIZATION
+#if FEATURE_CORECLR
                     else
                     if(propertyNames[i]=="NATIVE_DLL_SEARCH_DIRECTORIES")
                     {
@@ -3804,7 +3803,8 @@ namespace System {
                             if (Path.IsRelative(path))
                                 throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
 
-                            string appPath=Path.NormalizePath(path,true);
+                            string appPath = NormalizePath(path, fullCheck: true);
+
                             normalisedAppPathList.Append(appPath);
                             normalisedAppPathList.Append(Path.PathSeparator);
                         }
@@ -3813,7 +3813,7 @@ namespace System {
                         {
                             normalisedAppPathList.Remove(normalisedAppPathList.Length - 1, 1);
                         }
-                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly                
+                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly
                     }
                     else
                     if(propertyNames[i]=="PLATFORM_RESOURCE_ROOTS")
@@ -3831,7 +3831,8 @@ namespace System {
                             if (Path.IsRelative(path))
                                 throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
 
-                            string appPath=Path.NormalizePath(path,true);
+                            string appPath = NormalizePath(path, fullCheck: true);
+
                             normalisedAppPathList.Append(appPath);
                             normalisedAppPathList.Append(Path.PathSeparator);
                         }
@@ -3840,7 +3841,7 @@ namespace System {
                         {
                             normalisedAppPathList.Remove(normalisedAppPathList.Length - 1, 1);
                         }
-                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly                
+                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly
                     }
                     else
                     if(propertyNames[i]=="APP_PATHS")
@@ -3858,7 +3859,8 @@ namespace System {
                             if (Path.IsRelative(path))
                                 throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
 
-                            string appPath=Path.NormalizePath(path,true);
+                            string appPath = NormalizePath(path, fullCheck: true);
+
                             normalisedAppPathList.Append(appPath);
                             normalisedAppPathList.Append(Path.PathSeparator);
                         }
@@ -3867,7 +3869,7 @@ namespace System {
                         {
                             normalisedAppPathList.Remove(normalisedAppPathList.Length - 1, 1);
                         }
-                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly                
+                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly
                     }
                     else
                     if(propertyNames[i]=="APP_NI_PATHS")
@@ -3885,7 +3887,8 @@ namespace System {
                             if (Path.IsRelative(path))
                                 throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
 
-                            string appPath=Path.NormalizePath(path,true);
+                            string appPath = NormalizePath(path, fullCheck: true);
+
                             normalisedAppPathList.Append(appPath);
                             normalisedAppPathList.Append(Path.PathSeparator);
                         }
@@ -3894,12 +3897,12 @@ namespace System {
                         {
                             normalisedAppPathList.Remove(normalisedAppPathList.Length - 1, 1);
                         }
-                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly                
+                        ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null);        // not supported by fusion, so set explicitly
                     }
                     else
                     if(propertyNames[i]!= null)
                     {
-                        ad.SetDataHelper(propertyNames[i],propertyValues[i],null);     // just propagate                   
+                        ad.SetDataHelper(propertyNames[i],propertyValues[i],null);     // just propagate
                     }
 #endif
 
@@ -3993,6 +3996,19 @@ namespace System {
 #endif // FEATURE_CLICKONCE
         }
 
+        [SecuritySafeCritical]
+        internal static string NormalizePath(string path, bool fullCheck)
+        {
+            // We have to directly hit LegacyNormalizePath to avoid loading quirks for
+            // the AppDomain. (Once we have runtime support for long paths we can
+            // use the new normalization in path, but we still need to go in directly
+            // to avoid quirks.)
+            return  Path.LegacyNormalizePath(
+                path: path,
+                fullCheck: fullCheck,
+                maxPathLength: PathInternal.MaxShortPath,
+                expandShortPaths: true);
+        }
 
 #if FEATURE_APTCA
         // Called from DomainAssembly in Conditional APTCA cases
@@ -4654,7 +4670,7 @@ namespace System {
         [System.Security.SecuritySafeCritical]  // auto-generated
         [ResourceExposure(ResourceScope.None)]
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
-        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]              
+        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
         internal extern Int32 GetId();
         
         internal const Int32 DefaultADID = 1;
@@ -4675,6 +4691,7 @@ namespace System {
             Contract.Assert(i != -1, "invalid image location");
 
             AppDomainSetup info = new AppDomainSetup();
+
             info.ApplicationBase = imageLocation.Substring(0, i+1);
 
             StringBuilder config = new StringBuilder(imageLocation.Substring(i+1));
@@ -4685,7 +4702,7 @@ namespace System {
         }
 
         // Used by the validator for testing but not executing an assembly
-#if FEATURE_REMOTING        
+#if FEATURE_REMOTING
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
         private static AppDomain InternalCreateDomain(String imageLocation)
index a8a864ac12af73077d16bc0cf2cb0776beb3e5d6..49d20cd66978aede68ca7095a27393c7c3f73107 100644 (file)
@@ -372,7 +372,7 @@ namespace System {
         // Converts an array of bytes into a String.  
         public static String ToString (byte[] value, int startIndex, int length) {            
             if (value == null) {
-                throw new ArgumentNullException("byteArray");
+                throw new ArgumentNullException("value");
             }
 
             if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) {  // Don't throw for a 0 length array.
index 1c0fb31377f9cf358f64c8709f2397aacfc153da..247c7dfe2871a9e22c0969aa8e0fd2f7eac9ea78 100644 (file)
@@ -79,18 +79,18 @@ namespace System.Deployment.Internal.Isolation.Manifest {
 
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        internal static string GetEntryPointFullPath (ActivationContext activationContext) {
+        internal static string GetEntryPointFullPath (ActivationContext activationContext)
+        {
             string file, parameters;
             GetEntryPoint(activationContext, out file, out parameters);
 
-            if (!String.IsNullOrEmpty(file)) {
+            if (!string.IsNullOrEmpty(file))
+            {
                 string directoryName = activationContext.ApplicationDirectory;
-                if (directoryName == null || directoryName.Length == 0) {
+                if (directoryName == null || directoryName.Length == 0)
+                {
                     // If we were passed a relative path, assume the app base is the current working directory
-                    StringBuilder sb = new StringBuilder(Path.MAX_PATH + 1);
-                    if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0)
-                        System.IO.__Error.WinIOError();
-                    directoryName = sb.ToString();
+                    directoryName = Directory.UnsafeGetCurrentDirectory();
                 }
 
                 file = Path.Combine(directoryName, file);
index cd70bfb23e31d17556dd21495f9cf8fdb0bd5725..08844d397a441e04f2056b80cac72ca093d3892b 100644 (file)
@@ -833,6 +833,15 @@ namespace System.Diagnostics.Tracing
         {
             collector.AddBinary(value);
         }
+        
+        public override object GetData(object value)
+        {
+            object val = base.GetData(value);
+            if (null == val)
+                val = "";
+
+            return val;
+        }
     }
 
     /// <summary>
index d620ff96357e9c80b22aed96bcd42b7e6c0b3bf8..ae38d4fde59e63969dd9d575bf24fe9589ff5c04 100644 (file)
@@ -460,6 +460,7 @@ namespace System.Diagnostics.Tracing
                     }
 
                     this.WriteEventRaw(
+                        eventName,
                         ref descriptor,
                         activityID,
                         childActivityID,
@@ -564,6 +565,7 @@ namespace System.Diagnostics.Tracing
                     }
 
                     this.WriteEventRaw(
+                        eventName,
                         ref descriptor,
                         activityID,
                         childActivityID,
@@ -646,6 +648,7 @@ namespace System.Diagnostics.Tracing
                             eventTypes.typeInfo.WriteData(TraceLoggingDataCollector.Instance, ref data);
                             
                             this.WriteEventRaw(
+                                eventName,
                                 ref descriptor,
                                 pActivityId,
                                 pRelatedActivityId,
@@ -665,7 +668,7 @@ namespace System.Diagnostics.Tracing
                             if (ex is EventSourceException)
                                 throw;
                             else
-                                ThrowEventSourceException(ex);
+                                ThrowEventSourceException(eventName, ex);
                         }
                         finally
                         {
@@ -679,7 +682,7 @@ namespace System.Diagnostics.Tracing
                 if (ex is EventSourceException)
                     throw;
                 else
-                    ThrowEventSourceException(ex);
+                    ThrowEventSourceException(eventName, ex);
             }
         }
 
@@ -703,7 +706,7 @@ namespace System.Diagnostics.Tracing
                 eventCallbackArgs.PayloadNames = new ReadOnlyCollection<string>((IList<string>)payload.Keys);
             }
 
-            DisptachToAllListeners(-1, pActivityId, eventCallbackArgs);
+            DispatchToAllListeners(-1, pActivityId, eventCallbackArgs);
         }
 
 #if !ES_BUILD_PCL
index 1d1f1e708fe1d35bb72cf3a2c58f59e8fa8c4e58..ed5ffeca906ac08d93ba29c1155089ea830d5427 100644 (file)
@@ -99,7 +99,7 @@ namespace System.Diagnostics.Tracing
                 var newGroup = new FieldMetadata(
                     name,
                     TraceLoggingDataType.Struct,
-                    0,
+                    this.Tags,
                     this.BeginningBufferedArray);
                 this.AddField(newGroup);
                 result = new TraceLoggingMetadataCollector(this, newGroup);
index 633183d941aea353996b485c6e481eb339b35da4..bdfa364fe10cce65197fdc51f61f7c99cc8bd731 100644 (file)
@@ -1,8 +1,6 @@
 using System;
 using System.Diagnostics;
 using System.Threading;
-using System.Threading.Tasks;
-
 #if !ES_BUILD_AGAINST_DOTNET_V35
 using Contract = System.Diagnostics.Contracts.Contract;
 #else
@@ -11,15 +9,16 @@ using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
 
 #if ES_BUILD_STANDALONE
 namespace Microsoft.Diagnostics.Tracing
-#else
+#else    
+using System.Threading.Tasks;
 namespace System.Diagnostics.Tracing
 #endif
 {
     /// <summary>
-    /// Tracks activities.  This is meant to be a singledon (accessed by the ActivityTracer.Instance static property)
+    /// Tracks activities.  This is meant to be a singleton (accessed by the ActivityTracer.Instance static property)
     ///  
     /// Logically this is simply holds the m_current variable that holds the async local that holds the current ActivityInfo
-    /// An ActivityInfo is represents a actvity (which knows its creator and thus knows its path). 
+    /// An ActivityInfo is represents a activity (which knows its creator and thus knows its path). 
     ///
     /// Most of the magic is in the async local (it gets copied to new tasks)
     /// 
@@ -39,7 +38,7 @@ namespace System.Diagnostics.Tracing
     /// On any normal event log the event with activityTracker.CurrentActivityId
     /// </summary>
     internal class ActivityTracker
-    { 
+    {
 
         /// <summary>
         /// Called on work item begins.  The activity name = providerName + activityName without 'Start' suffix.
@@ -55,15 +54,32 @@ namespace System.Diagnostics.Tracing
         public void OnStart(string providerName, string activityName, int task, ref Guid activityId, ref Guid relatedActivityId, EventActivityOptions options)
         {
             if (m_current == null)        // We are not enabled
-                return;
+            {
+                // We  used to rely on the TPL provider turning us on, but that has the disadvantage that you don't get Start-Stop tracking
+                // until you use Tasks for the first time (which you may never do).   Thus we change it to pull rather tan push for whether
+                // we are enabled.   
+                if (m_checkedForEnable)
+                    return;
+                m_checkedForEnable = true;
+#if ES_BUILD_STANDALONE
+                Enable();           // Enable it unconditionally.  
+#else
+                if (System.Threading.Tasks.TplEtwProvider.Log.IsEnabled(EventLevel.Informational, System.Threading.Tasks.TplEtwProvider.Keywords.TasksFlowActivityIds))
+                     Enable();
+#endif
+                if(m_current == null)
+                {
+                    return;
+                }
+            }
 
             Contract.Assert((options & EventActivityOptions.Disable) == 0);
 
             var currentActivity = m_current.Value;
             var fullActivityName = NormalizeActivityName(providerName, activityName, task);
-            
+
             var etwLog = TplEtwProvider.Log;
-            if (etwLog.Debug) 
+            if (etwLog.Debug)
             {
                 etwLog.DebugFacilityMessage("OnStartEnter", fullActivityName);
                 etwLog.DebugFacilityMessage("OnStartEnterActivityState", ActivityInfo.LiveActivities(currentActivity));
@@ -100,17 +116,17 @@ namespace System.Diagnostics.Tracing
             else
                 id = Interlocked.Increment(ref currentActivity.m_lastChildID);
 
-            // Remember the previous ID so we can log it
-            relatedActivityId = currentActivity != null ? currentActivity.ActivityId : Guid.Empty;
+            // The previous ID is my 'causer' and becomes my related activity ID
+            relatedActivityId = EventSource.CurrentThreadActivityId;
 
             // Add to the list of started but not stopped activities. 
-            ActivityInfo newActivity = new ActivityInfo(fullActivityName, id, currentActivity, options);
+            ActivityInfo newActivity = new ActivityInfo(fullActivityName, id, currentActivity, relatedActivityId, options);
             m_current.Value = newActivity;
 
             // Remember the current ID so we can log it 
             activityId = newActivity.ActivityId;
 
-            if (etwLog.Debug) 
+            if (etwLog.Debug)
             {
                 etwLog.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(newActivity));
                 etwLog.DebugFacilityMessage1("OnStartRet", activityId.ToString(), relatedActivityId.ToString());
@@ -119,7 +135,7 @@ namespace System.Diagnostics.Tracing
 
         /// <summary>
         /// Called when a work item stops.  The activity name = providerName + activityName without 'Stop' suffix.
-        /// It updates CurrentActivityId to track this fact.   The Stop event associated with stop should log the ActivityID associated with the event.
+        /// It updates m_current variable to track this fact.   The Stop event associated with stop should log the ActivityID associated with the event.
         ///
         /// If activity tracing is not on, then activityId and relatedActivityId are not set
         /// </summary>
@@ -131,13 +147,13 @@ namespace System.Diagnostics.Tracing
             var fullActivityName = NormalizeActivityName(providerName, activityName, task);
 
             var etwLog = TplEtwProvider.Log;
-            if (etwLog.Debug) 
+            if (etwLog.Debug)
             {
                 etwLog.DebugFacilityMessage("OnStopEnter", fullActivityName);
                 etwLog.DebugFacilityMessage("OnStopEnterActivityState", ActivityInfo.LiveActivities(m_current.Value));
             }
 
-            for (; ;) // This is a retry loop.
+            for (; ; ) // This is a retry loop.
             {
                 ActivityInfo currentActivity = m_current.Value;
                 ActivityInfo newCurrentActivity = null;               // if we have seen any live activities (orphans), at he first one we have seen.   
@@ -193,7 +209,7 @@ namespace System.Diagnostics.Tracing
 
                     m_current.Value = newCurrentActivity;
 
-                    if (etwLog.Debug) 
+                    if (etwLog.Debug)
                     {
                         etwLog.DebugFacilityMessage("OnStopRetActivityState", ActivityInfo.LiveActivities(newCurrentActivity));
                         etwLog.DebugFacilityMessage("OnStopRet", activityId.ToString());
@@ -210,12 +226,12 @@ namespace System.Diagnostics.Tracing
         [System.Security.SecuritySafeCritical]
         public void Enable()
         {
-            if (m_current == null) 
+            if (m_current == null)
             {
                 m_current = new AsyncLocal<ActivityInfo>(ActivityChanging);
             }
         }
-        
+
         /// <summary>
         /// An activity tracker is a singleton, this is how you get the one and only instance.
         /// </summary>
@@ -263,24 +279,25 @@ namespace System.Diagnostics.Tracing
 
         // *******************************************************************************
         /// <summary>
-        /// An ActivityInfo repesents a particular activity.   It is almost read-only the only
+        /// An ActivityInfo represents a particular activity.   It is almost read-only.   The only
         /// fields that change after creation are
         ///    m_lastChildID - used to generate unique IDs for the children activities and for the most part can be ignored.
         ///    m_stopped - indicates that this activity is dead 
-        /// This read-only ness is important because an activity's  m_creator chain forms the 
+        /// This read-only-ness is important because an activity's  m_creator chain forms the 
         /// 'Path of creation' for the activity (which is also its unique ID) but is also used as
         /// the 'list of live parents' which indicate of those ancestors, which are alive (if they
         /// are not marked dead they are alive).   
         /// </summary>
         private class ActivityInfo
         {
-            public ActivityInfo(string name,  long uniqueId, ActivityInfo creator, EventActivityOptions options)
+            public ActivityInfo(string name, long uniqueId, ActivityInfo creator, Guid activityIDToRestore, EventActivityOptions options)
             {
                 m_name = name;
                 m_eventOptions = options;
                 m_creator = creator;
                 m_uniqueId = uniqueId;
                 m_level = creator != null ? creator.m_level + 1 : 0;
+                m_activityIdToRestore = activityIDToRestore;
 
                 // Create a nice GUID that encodes the chain of activities that started this one.
                 CreateActivityPathGuid(out m_guid, out m_activityPathGuidOffset);
@@ -294,19 +311,19 @@ namespace System.Diagnostics.Tracing
                 }
             }
 
-            public static string Path(ActivityInfo activityInfo) 
+            public static string Path(ActivityInfo activityInfo)
             {
                 if (activityInfo == null)
-                    return("");
+                    return ("");
                 return Path(activityInfo.m_creator) + "/" + activityInfo.m_uniqueId;
             }
 
-            public override string ToString() 
+            public override string ToString()
             {
                 string dead = "";
                 if (m_stopped != 0)
-                   dead = ",DEAD";
-                 return m_name + "(" + Path(this) + dead + ")";
+                    dead = ",DEAD";
+                return m_name + "(" + Path(this) + dead + ")";
             }
 
             public static string LiveActivities(ActivityInfo list)
@@ -331,10 +348,10 @@ namespace System.Diagnostics.Tracing
             /// (rooted in an activity that predates activity tracking.  
             ///
             /// We wish to encode this path in the Guid to the extent that we can.  Many of the paths have
-            /// many small numbers in them and we take advatage of this in the encoding to output as long
+            /// many small numbers in them and we take advantage of this in the encoding to output as long
             /// a path in the GUID as possible.   
             /// 
-            /// Because of the possiblility of GUID collistion, we only use 96 of the 128 bits of the GUID
+            /// Because of the possibility of GUID collision, we only use 96 of the 128 bits of the GUID
             /// for encoding the path.  The last 32 bits are a simple checksum (and random number) that 
             /// identifies this as using the convention defined here.   
             ///
@@ -347,7 +364,7 @@ namespace System.Diagnostics.Tracing
             [System.Security.SecuritySafeCritical]
             private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset)
             {
-                fixed (Guid* outPtr = &idRet) 
+                fixed (Guid* outPtr = &idRet)
                 {
                     int activityPathGuidOffsetStart = 0;
                     if (m_creator != null)
@@ -355,13 +372,18 @@ namespace System.Diagnostics.Tracing
                         activityPathGuidOffsetStart = m_creator.m_activityPathGuidOffset;
                         idRet = m_creator.m_guid;
                     }
-                    else 
+                    else
                     {
-                        // We start with the appdomain number to make this unique among appdomains.                      
-                        activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint) System.Threading.Thread.GetDomainID());
+                        // 
+                        int appDomainID = 0;
+#if !ES_BUILD_PCL  
+                        appDomainID = System.Threading.Thread.GetDomainID();
+#endif
+                        // We start with the appdomain number to make this unique among appdomains.
+                        activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)appDomainID);
                     }
 
-                    activityPathGuidOffset = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint) m_uniqueId);
+                    activityPathGuidOffset = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)m_uniqueId);
 
 
                     // If the path does not fit, Make a GUID by incrementing rather than as a path, keeping as much of the path as possible
@@ -372,19 +394,19 @@ namespace System.Diagnostics.Tracing
 
             /// <summary>
             /// If we can't fit the activity Path into the GUID we come here.   What we do is simply
-            /// generate a 4 byte number (s_nextOverflowId).  Then look for an anscesor that has  
+            /// generate a 4 byte number (s_nextOverflowId).  Then look for an ancestor that has  
             /// sufficient space for this ID.   By doing this, we preserve the fact that this activity
             /// is a child (of unknown depth) from that ancestor.
             /// </summary>
             [System.Security.SecurityCritical]
             private unsafe void CreateOverflowGuid(Guid* outPtr)
             {
-                // Seach backwards for an ancestor that has sufficient space to put the ID.  
-                for(ActivityInfo ancestor = m_creator; ancestor != null; ancestor = ancestor.m_creator)
+                // Search backwards for an ancestor that has sufficient space to put the ID.  
+                for (ActivityInfo ancestor = m_creator; ancestor != null; ancestor = ancestor.m_creator)
                 {
                     if (ancestor.m_activityPathGuidOffset <= 10)  // we need at least 2 bytes.  
                     {
-                        uint id = (uint) Interlocked.Increment(ref ancestor.m_lastChildID);        // Get a unique ID 
+                        uint id = unchecked((uint)Interlocked.Increment(ref ancestor.m_lastChildID));        // Get a unique ID 
                         // Try to put the ID into the GUID
                         *outPtr = ancestor.m_guid;
                         int endId = AddIdToGuid(outPtr, ancestor.m_activityPathGuidOffset, id, true);
@@ -397,8 +419,8 @@ namespace System.Diagnostics.Tracing
             }
 
             /// <summary>
-            /// The encoding for a list of numbers used to make Activity  Guids.   Basically
-            /// we operate on nibbles (which are nice becase they show up as hex digits).  The
+            /// The encoding for a list of numbers used to make Activity  GUIDs.   Basically
+            /// we operate on nibbles (which are nice because they show up as hex digits).  The
             /// list is ended with a end nibble (0) and depending on the nibble value (Below)
             /// the value is either encoded into nibble itself or it can spill over into the
             /// bytes that follow.   
@@ -409,18 +431,18 @@ namespace System.Diagnostics.Tracing
                 LastImmediateValue = 0xA,
 
                 PrefixCode = 0xB,      // all the 'long' encodings go here.  If the next nibble is MultiByte1-4
-                                       // than this is a 'overflow' id.   Unlike the hierarchitcal IDs these are 
-                                       // allocated densly but don't tell you anything about nesting. we use 
-                                       // these when we run out of space in the GUID to store the path.
+                // than this is a 'overflow' id.   Unlike the hierarchical IDs these are 
+                // allocated densely but don't tell you anything about nesting. we use 
+                // these when we run out of space in the GUID to store the path.
 
                 MultiByte1 = 0xC,   // 1 byte follows.  If this Nibble is in the high bits, it the high bits of the number are stored in the low nibble.   
                 // commented out because the code does not explicitly reference the names (but they are logically defined).  
-                // MultiByte2 = 0xD,   // 2 bytes follow (we don't bother with the nibble optimzation)
-                // MultiByte3 = 0xE,   // 3 bytes follow (we don't bother with the nibble optimzation)
-                // MultiByte4 = 0xF,   // 4 bytes follow (we don't bother with the nibble optimzation)
+                // MultiByte2 = 0xD,   // 2 bytes follow (we don't bother with the nibble optimization)
+                // MultiByte3 = 0xE,   // 3 bytes follow (we don't bother with the nibble optimization)
+                // MultiByte4 = 0xF,   // 4 bytes follow (we don't bother with the nibble optimization)
             }
 
-            /// Add the acivity id 'id' to the output Guid 'outPtr' starting at the offset 'whereToAddId'
+            /// Add the activity id 'id' to the output Guid 'outPtr' starting at the offset 'whereToAddId'
             /// Thus if this number is 6 that is where 'id' will be added.    This will return 13 (12
             /// is the maximum number of bytes that fit in a GUID) if the path did not fit.  
             /// If 'overflow' is true, then the number is encoded as an 'overflow number (which has a
@@ -450,9 +472,9 @@ namespace System.Diagnostics.Tracing
                     {
                         if (endPtr <= ptr + 2)        // I need at least 2 bytes
                             return 13;
-                        
+
                         // Write out the prefix code nibble and the length nibble 
-                        WriteNibble(ref ptr, endPtr, (uint) NumberListCodes.PrefixCode);
+                        WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.PrefixCode);
                     }
                     // The rest is the same for overflow and non-overflow case
                     WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.MultiByte1 + (len - 1));
@@ -460,7 +482,7 @@ namespace System.Diagnostics.Tracing
                     // Do we have an odd nibble?   If so flush it or use it for the 12 byte case.   
                     if (ptr < endPtr && *ptr != 0)
                     {
-                        // If the value < 4096 we can use the nibble we are otherwise just outputing as padding. 
+                        // If the value < 4096 we can use the nibble we are otherwise just outputting as padding. 
                         if (id < 4096)
                         {
                             // Indicate this is a 1 byte multicode with 4 high order bits in the lower nibble.  
@@ -471,7 +493,7 @@ namespace System.Diagnostics.Tracing
                     }
 
                     // Write out the bytes.
-                    while(0 < len)
+                    while (0 < len)
                     {
                         if (endPtr <= ptr)
                         {
@@ -514,14 +536,15 @@ namespace System.Diagnostics.Tracing
             #endregion // CreateGuidForActivityPath
 
             readonly internal string m_name;                        // The name used in the 'start' and 'stop' APIs to help match up
-            readonly long m_uniqueId;                                    // a small number that makes this activity unique among its siblings
-            internal readonly Guid m_guid;                          // Activity Guid, it is bascially an encoding of the Path() (see CreateActivityPathGuid)
+            readonly long m_uniqueId;                               // a small number that makes this activity unique among its siblings
+            internal readonly Guid m_guid;                          // Activity Guid, it is basically an encoding of the Path() (see CreateActivityPathGuid)
             internal readonly int m_activityPathGuidOffset;         // Keeps track of where in m_guid the causality path stops (used to generated child GUIDs)
             internal readonly int m_level;                          // current depth of the Path() of the activity (used to keep recursion under control)
             readonly internal EventActivityOptions m_eventOptions;  // Options passed to start. 
             internal long m_lastChildID;                            // used to create a unique ID for my children activities
             internal int m_stopped;                                 // This work item has stopped
             readonly internal ActivityInfo m_creator;               // My parent (creator).  Forms the Path() for the activity.
+            readonly internal Guid m_activityIdToRestore;           // The Guid to restore after a stop.   
             #endregion
         }
 
@@ -530,26 +553,50 @@ namespace System.Diagnostics.Tracing
         // with m_current.ActivityID
         void ActivityChanging(AsyncLocalValueChangedArgs<ActivityInfo> args)
         {
-            if (args.PreviousValue == args.CurrentValue)
-                return;
+            ActivityInfo cur =  args.CurrentValue;
+            ActivityInfo prev = args.PreviousValue;
 
-            if (args.CurrentValue != null)
+            // Are we popping off a value?   (we have a prev, and it creator is cur) 
+            // Then check if we should use the GUID at the time of the start event
+            if (prev != null && prev.m_creator == cur)
             {
-                // Allow subsequent activities inside this thread to automatically get the current activity ID.
-                EventSource.SetCurrentThreadActivityId(args.CurrentValue.ActivityId);
+                // If the saved activity ID is not the same as the creator activity
+                // that takes precedence (it means someone explicitly did a SetActivityID)
+                // Set it to that and get out
+                if (cur == null || prev.m_activityIdToRestore != cur.ActivityId)
+                {
+                    EventSource.SetCurrentThreadActivityId(prev.m_activityIdToRestore);
+                    return;
+                }
             }
-            else
-                EventSource.SetCurrentThreadActivityId(Guid.Empty);
+
+            // OK we did not have an explicit SetActivityID set.   Then we should be 
+            // setting the activity to current ActivityInfo.  However that activity 
+            // might be dead, in which case we should skip it, so we never set 
+            // the ID to dead things.   
+            while(cur != null)
+            {
+                // We found a live activity (typically the first time), set it to that.  
+                if (cur.m_stopped == 0)
+                {
+                    EventSource.SetCurrentThreadActivityId(cur.ActivityId);
+                    return;
+                }
+                cur = cur.m_creator;
+            }
+            // we can get here if there is no information on our activity stack (everything is dead)
+            // currently we do nothing, as that seems better than setting to Guid.Emtpy.  
         }
 
         /// <summary>
-        /// Async local variables have the propery that the are automatically copied whenever a task is created and used
+        /// Async local variables have the properly that the are automatically copied whenever a task is created and used
         /// while that task is running.   Thus m_current 'flows' to any task that is caused by the current thread that
         /// last set it.   
         /// 
         /// This variable points a a linked list that represents all Activities that have started but have not stopped.  
         /// </summary>
         AsyncLocal<ActivityInfo> m_current;
+        bool m_checkedForEnable;
 
         // Singleton
         private static ActivityTracker s_activityTrackerInstance = new ActivityTracker();
@@ -557,8 +604,74 @@ namespace System.Diagnostics.Tracing
         // Used to create unique IDs at the top level.  Not used for nested Ids (each activity has its own id generator)
         static long m_nextId = 0;
         private const ushort MAX_ACTIVITY_DEPTH = 100;            // Limit maximum depth of activities to be tracked at 100. 
-                                                                  // This will avoid leaking memory in case of activities that are never stopped.
+        // This will avoid leaking memory in case of activities that are never stopped.
 
         #endregion
     }
+
+#if ES_BUILD_STANDALONE
+    /******************************** SUPPORT *****************************/
+    /// <summary>
+    /// This is supplied by the framework.   It is has the semantics that the value is copied to any new Tasks that is created
+    /// by the current task.   Thus all causally related code gets this value.    Note that reads and writes to this VARIABLE 
+    /// (not what it points it) to this does not need to be protected by locks because it is inherently thread local (you always
+    /// only get your thread local copy which means that you never have ----s.  
+    /// </summary>
+    /// 
+    [EventSource(Name="Microsoft.Tasks.Nuget")]
+    internal class TplEtwProvider : EventSource
+    {
+        public class Keywords
+        {
+            public const EventKeywords Debug = (EventKeywords) 1;
+        }
+
+        public static TplEtwProvider Log = new TplEtwProvider();
+        public bool Debug { get { return IsEnabled(EventLevel.Verbose, Keywords.Debug); } }
+
+        public void DebugFacilityMessage(string Facility, string Message) { WriteEvent(1, Facility, Message); }
+        public void DebugFacilityMessage1(string Facility, string Message, string Arg) { WriteEvent(2, Facility, Message, Arg); }
+        public void SetActivityId(Guid Id) { WriteEvent(3, Id); }
+    }
+#endif
+
+#if ES_BUILD_AGAINST_DOTNET_V35 || ES_BUILD_PCL || NO_ASYNC_LOCAL
+
+    internal sealed class AsyncLocalValueChangedArgs<T>
+    {
+        public AsyncLocalValueChangedArgs()
+        {
+        }
+
+        public T PreviousValue { get { return default(T); } }
+        public T CurrentValue { get { return default(T); } }
+
+    }
+
+    internal sealed class AsyncLocal<T>
+    {
+        public AsyncLocal()
+        {
+        }
+
+        public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler)
+        {
+
+        }
+
+        public T Value
+        {
+            get
+            {
+                object obj = null;  // 
+                return (obj == null) ? default(T) : (T)obj;
+            }
+            set
+            {
+                // 
+            }
+        }
+    }
+#endif
+
 }
index 8a3fec6e6f46cbb186f5cafe0a34a20330f3d8ff..939d15ee520f53b2b20ee8b9247098cd40e8ce0a 100644 (file)
@@ -91,7 +91,7 @@ namespace System.Diagnostics.Tracing
         private static WriteEventErrorCode s_returnCode; // The last return code 
 
         private const int s_basicTypeAllocationBufferSize = 16;
-        private const int s_etwMaxNumberArguments = 32;
+        private const int s_etwMaxNumberArguments = 128;
         private const int s_etwAPIMaxRefObjCount = 8;
         private const int s_maxEventDataDescriptors = 128;
         private const int s_traceEventMaximumSize = 65482;
index a1b51851218d5fc20ec8ab7c6933e742e0f6a94b..9ae566937256255d1b55dcc7c0b259983dc54595 100644 (file)
@@ -1,5 +1,4 @@
-// Copyright (c) Microsoft Corporation.  All rights reserved
-// Copyright (c) Microsoft Corporation.  All rights reserved
+// Copyright (c) Microsoft Corporation.  All rights reserved 
 // This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
 // It is available from http://www.codeplex.com/hyperAddin 
 #define FEATURE_MANAGED_ETW
@@ -13,7 +12,7 @@
 // #define FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
 #endif
 
-/* DESIGN NOTES DESIGN NOTES DESIGN NOTES DESIGN NOTES */
+/*  DESIGN NOTES DESIGN NOTES DESIGN NOTES DESIGN NOTES  */
 // DESIGN NOTES
 // Over the years EventSource has become more complex and so it is important to understand
 // the basic structure of the code to insure that it does not grow more complex.
 
 
 using System;
+using System.Runtime.CompilerServices;
 #if FEATURE_ACTIVITYSAMPLING
 using System.Collections.Concurrent;
 #endif
@@ -531,6 +531,7 @@ namespace System.Diagnostics.Tracing
 #if FEATURE_ACTIVITYSAMPLING
             Guid newId = activityId;
 #endif // FEATURE_ACTIVITYSAMPLING
+
             // We ignore errors to keep with the convention that EventSources do not throw errors.
             // Note we can't access m_throwOnWrites because this is a static method.  
             if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
@@ -594,7 +595,7 @@ namespace System.Diagnostics.Tracing
         /// </summary>
         public static Guid CurrentThreadActivityId
         {
-            [System.Security.SecurityCritical]
+            [System.Security.SecuritySafeCritical]
             get
             {
                 // We ignore errors to keep with the convention that EventSources do not throw 
@@ -680,6 +681,30 @@ namespace System.Diagnostics.Tracing
         /// </summary>
         public override string ToString() { return Environment.GetResourceString("EventSource_ToString", Name, Guid); }
 
+        /// <summary>
+        /// Fires when a Command (e.g. Enable) comes from a an EventListener.  
+        /// </summary>
+        public event EventHandler<EventCommandEventArgs> EventCommandExecuted
+        {
+            add
+            {
+                m_eventCommandExecuted += value;
+
+                // If we have an EventHandler<EventCommandEventArgs> attached to the EventSource before the first command arrives
+                // It should get a chance to handle the deferred commands.
+                EventCommandEventArgs deferredCommands = m_deferredCommands;
+                while (deferredCommands != null)
+                {
+                    value(this, deferredCommands);
+                    deferredCommands = deferredCommands.nextCommand;
+                }
+            }
+            remove
+            {
+                m_eventCommandExecuted -= value;
+            }
+        }
+
         #region protected
         /// <summary>
         /// This is the constructor that most users will use to create their eventSource.   It takes 
@@ -1152,7 +1177,7 @@ namespace System.Diagnostics.Tracing
                 {
                     Contract.Assert(m_eventData != null);  // You must have initialized this if you enabled the source.
                     if (relatedActivityId != null)
-                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId]);
+                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
 
 #if FEATURE_MANAGED_ETW
                     if (m_eventData[eventId].EnabledForETW)
@@ -1202,7 +1227,7 @@ namespace System.Diagnostics.Tracing
                                     // mask set to 0x0f so, when all ETW sessions want the event we don't need to 
                                     // synthesize a new one
                                     if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                                 else
                                 {
@@ -1222,7 +1247,7 @@ namespace System.Diagnostics.Tracing
                                         unchecked((long)etwSessions.ToEventKeywords() | origKwd));
 
                                     if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                             }
                             else
@@ -1252,7 +1277,7 @@ namespace System.Diagnostics.Tracing
                         if (!SelfDescribingEvents)
                         {
                             if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
-                                ThrowEventSourceException();
+                                ThrowEventSourceException(m_eventData[eventId].Name);
                         }
                         else
                         {
@@ -1286,7 +1311,7 @@ namespace System.Diagnostics.Tracing
                     if (ex is EventSourceException)
                         throw;
                     else
-                        ThrowEventSourceException(ex);
+                        ThrowEventSourceException(m_eventData[eventId].Name, ex);
                 }
             }
         }
@@ -1402,6 +1427,7 @@ namespace System.Diagnostics.Tracing
 #endif
         [SecurityCritical]
         private unsafe void WriteEventRaw(
+            string eventName,
             ref EventDescriptor eventDescriptor,
             Guid* activityID,
             Guid* relatedActivityID,
@@ -1410,12 +1436,12 @@ namespace System.Diagnostics.Tracing
         {
             if (m_provider == null)
             {
-                ThrowEventSourceException();
+                ThrowEventSourceException(eventName);
             }
             else
             {
                 if (!m_provider.WriteEventRaw(ref eventDescriptor, activityID, relatedActivityID, dataCount, data))
-                    ThrowEventSourceException();
+                    ThrowEventSourceException(eventName);
             }
         }
 
@@ -1516,10 +1542,13 @@ namespace System.Diagnostics.Tracing
             {
                 // If there are any deferred commands, we can do them now.   
                 // This is the most likely place for exceptions to happen.  
-                while (m_deferredCommands != null)
+                // Note that we are NOT resetting m_deferredCommands to NULL here, 
+                // We are giving for EventHandler<EventCommandEventArgs> that will be attached later
+                EventCommandEventArgs deferredCommands = m_deferredCommands;
+                while (deferredCommands != null)
                 {
-                    DoCommand(m_deferredCommands);      // This can never throw, it catches them and reports the errors.   
-                    m_deferredCommands = m_deferredCommands.nextCommand;
+                    DoCommand(deferredCommands);      // This can never throw, it catches them and reports the errors.   
+                    deferredCommands = deferredCommands.nextCommand;
                 }
             }
         }
@@ -1817,7 +1846,7 @@ namespace System.Diagnostics.Tracing
                 dataPointer = data->DataPointer;
                 data++;
                 for (int i = 0; i < cbSize; ++i)
-                    blob[i] = *((byte*)dataPointer);
+                    blob[i] = *((byte*)dataPointer + i);
                 return blob;
             }
             else if (dataType == typeof(byte*))
@@ -1863,8 +1892,24 @@ namespace System.Diagnostics.Tracing
                 {
                     Contract.Assert(m_eventData != null);  // You must have initialized this if you enabled the source.  
                     if (childActivityID != null)
-                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId]);
-
+                    {
+                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
+
+                        // If you use WriteEventWithRelatedActivityID you MUST declare the first argument to be a GUID 
+                        // with the name 'relatedActivityID, and NOT pass this argument to the WriteEvent method.  
+                        // During manifest creation we modify the ParameterInfo[] that we store to strip out any
+                        // first parameter that is of type Guid and named "relatedActivityId." Thus, if you call
+                        // WriteEventWithRelatedActivityID from a method that doesn't name its first parameter correctly
+                        // we can end up in a state where the ParameterInfo[] doesn't have its first parameter stripped,
+                        // and this leads to a mismatch between the number of arguments and the number of ParameterInfos,
+                        // which would cause a cryptic IndexOutOfRangeException later if we don't catch it here.
+                        if (!m_eventData[eventId].HasRelatedActivityID)
+                        {
+                            throw new ArgumentException(Environment.GetResourceString("EventSource_NoRelatedActivityId"));
+                        }
+                    }
+                    
+                    LogEventArgsMismatches(m_eventData[eventId].Parameters, args);
 #if FEATURE_MANAGED_ETW
                     if (m_eventData[eventId].EnabledForETW)
                     {
@@ -1909,7 +1954,7 @@ namespace System.Diagnostics.Tracing
                                     // mask set to 0x0f so, when all ETW sessions want the event we don't need to 
                                     // synthesize a new one
                                     if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                                 else
                                 {
@@ -1926,7 +1971,7 @@ namespace System.Diagnostics.Tracing
                                         unchecked((long)(ulong)etwSessions | origKwd));
 
                                     if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                             }
                             else
@@ -1956,7 +2001,7 @@ namespace System.Diagnostics.Tracing
                         if (!SelfDescribingEvents)
                         {
                             if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
-                                ThrowEventSourceException();
+                                ThrowEventSourceException(m_eventData[eventId].Name);
                         }
                         else
                         {
@@ -2003,7 +2048,7 @@ namespace System.Diagnostics.Tracing
                     if (ex is EventSourceException)
                         throw;
                     else
-                        ThrowEventSourceException(ex);
+                        ThrowEventSourceException(m_eventData[eventId].Name, ex);
                 }
             }
         }
@@ -2027,11 +2072,71 @@ namespace System.Diagnostics.Tracing
             return eventData;
         }
 
+        /// <summary>
+        /// We expect that the arguments to the Event method and the arguments to WriteEvent match. This function 
+        /// checks that they in fact match and logs a warning to the debugger if they don't.
+        /// </summary>
+        /// <param name="infos"></param>
+        /// <param name="args"></param>
+        private void LogEventArgsMismatches(ParameterInfo[] infos, object[] args)
+        {
+            // It would be nice to have this on PCL builds, but it would be pointless since there isn't support for 
+            // writing to the debugger log on PCL.
+            bool typesMatch = args.Length == infos.Length;
+
+            int i = 0;
+            while (typesMatch && i < args.Length)
+            {
+                Type pType = infos[i].ParameterType;
+
+                // Checking to see if the Parameter types (from the Event method) match the supplied argument types.
+                // Fail if one of two things hold : either the argument type is not equal to the parameter type, or the 
+                // argument is null and the parameter type is non-nullable.
+                if ((args[i] != null && (args[i].GetType() != pType))
+                    || (args[i] == null && (!(pType.IsGenericType && pType.GetGenericTypeDefinition() == typeof(Nullable<>))))
+                    )
+                {
+                    typesMatch = false;
+                    break;
+                }
+
+                ++i;
+            }
+
+            if (!typesMatch)
+            {
+                System.Diagnostics.Debugger.Log(0, null, Environment.GetResourceString("EventSource_VarArgsParameterMismatch") + "\r\n");
+            }
+        }
+
+        private int GetParamLengthIncludingByteArray(ParameterInfo[] parameters)
+        {
+            int sum = 0;
+            foreach(ParameterInfo info in parameters)
+            {
+                if(info.ParameterType == typeof(byte[]))
+                {
+                    sum += 2;
+                }
+                else
+                {
+                    sum++;
+                }
+            }
+
+            return sum;
+        }
+
         [SecurityCritical]
         unsafe private 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
+            // that the number of parameters is correct against the byte[] case, but also we the args array would be one too long if
+            // we just used the modifiedParamCount here -- so we need both.
             int paramCount = m_eventData[eventId].Parameters.Length;
-            if (eventDataCount != paramCount)
+            int modifiedParamCount = GetParamLengthIncludingByteArray(m_eventData[eventId].Parameters);
+            if (eventDataCount != modifiedParamCount)
             {
                 ReportOutOfBandMessage(Environment.GetResourceString("EventSource_EventParametersMismatch", eventId, eventDataCount, paramCount), true);
                 paramCount = Math.Min(paramCount, eventDataCount);
@@ -2057,11 +2162,11 @@ namespace System.Diagnostics.Tracing
             eventCallbackArgs.Message = m_eventData[eventId].Message;
             eventCallbackArgs.Payload = new ReadOnlyCollection<object>(args);
 
-            DisptachToAllListeners(eventId, childActivityID, eventCallbackArgs);
+            DispatchToAllListeners(eventId, childActivityID, eventCallbackArgs);
         }
 
         [SecurityCritical]
-        private unsafe void DisptachToAllListeners(int eventId, Guid* childActivityID, EventWrittenEventArgs eventCallbackArgs)
+        private unsafe void DispatchToAllListeners(int eventId, Guid* childActivityID, EventWrittenEventArgs eventCallbackArgs)
         {
             Exception lastThrownException = null;
             for (EventDispatcher dispatcher = m_Dispatchers; dispatcher != null; dispatcher = dispatcher.m_Next)
@@ -2304,9 +2409,9 @@ namespace System.Diagnostics.Tracing
 
         }
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
-        private void ThrowEventSourceException(Exception innerEx = null)
+        private void ThrowEventSourceException(string eventName, Exception innerEx = null)
         {
-            // If we fail during ouf of band logging we may end up trying 
+            // If we fail during out of band logging we may end up trying 
             // to throw another EventSourceException, thus hitting a StackOverflowException. 
             // Avoid StackOverflow by making sure we do not recursively call this method.
             if (m_EventSourceExceptionRecurenceCount > 0)
@@ -2315,30 +2420,36 @@ namespace System.Diagnostics.Tracing
             {
                 m_EventSourceExceptionRecurenceCount++;
 
+                string errorPrefix = "EventSourceException";
+                if(eventName != null)
+                {
+                    errorPrefix += " while processing event \"" + eventName + "\"";
+                }
+
                 // 
                 switch (EventProvider.GetLastWriteEventError())
                 {
                     case EventProvider.WriteEventErrorCode.EventTooBig:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_EventTooBig"), true);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Environment.GetResourceString("EventSource_EventTooBig"), true);
                         if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_EventTooBig"), innerEx);
                         break;
                     case EventProvider.WriteEventErrorCode.NoFreeBuffers:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_NoFreeBuffers"), true);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Environment.GetResourceString("EventSource_NoFreeBuffers"), true);
                         if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_NoFreeBuffers"), innerEx);
                         break;
                     case EventProvider.WriteEventErrorCode.NullInput:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_NullInput"), true);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Environment.GetResourceString("EventSource_NullInput"), true);
                         if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_NullInput"), innerEx);
                         break;
                     case EventProvider.WriteEventErrorCode.TooManyArgs:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_TooManyArgs"), true);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Environment.GetResourceString("EventSource_TooManyArgs"), true);
                         if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_TooManyArgs"), innerEx);
                         break;
                     default:
                         if (innerEx != null)
-                            ReportOutOfBandMessage("EventSourceException: " + innerEx.GetType() + ":" + innerEx.Message, true);
+                            ReportOutOfBandMessage(errorPrefix + ": " + innerEx.GetType() + ":" + innerEx.Message, true);
                         else
-                            ReportOutOfBandMessage("EventSourceException", true);
+                            ReportOutOfBandMessage(errorPrefix, true);
                         if (ThrowOnEventWriteErrors) throw new EventSourceException(innerEx);
                         break;
                 }
@@ -2349,18 +2460,20 @@ namespace System.Diagnostics.Tracing
             }
         }
 
-        private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData)
+        private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData, string eventName)
         {
             if ((EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Send &&
-                (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Receive)
+                (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Receive &&
+                (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Start)
             {
-                ThrowEventSourceException();
+                ThrowEventSourceException(eventName);
             }
         }
 
         internal static EventOpcode GetOpcodeWithDefault(EventOpcode opcode, string eventName)
         {
-            if (opcode == EventOpcode.Info)
+            if (opcode == EventOpcode.Info && eventName != null)
             {
                 if (eventName.EndsWith(s_ActivityStartSuffix))
                 {
@@ -2408,6 +2521,8 @@ namespace System.Diagnostics.Tracing
             public EventTags Tags;
             public bool EnabledForAnyListener;      // true if any dispatcher has this event turned on
             public bool EnabledForETW;              // is this event on for the OS ETW data dispatcher?
+            
+            public bool HasRelatedActivityID;       // Set if the event method's first parameter is a Guid named 'relatedActivityId'
 #if !FEATURE_ACTIVITYSAMPLING
 #pragma warning disable 0649
 #endif
@@ -2457,8 +2572,13 @@ namespace System.Diagnostics.Tracing
             var commandArgs = new EventCommandEventArgs(command, commandArguments, this, listener, perEventSourceSessionId, etwSessionId, enable, level, matchAnyKeyword);
             lock (EventListener.EventListenersLock)
             {
-                if (m_completelyInited)     // We are fully initialized, do the command 
+                if (m_completelyInited)     
+                {
+                    // After the first command arrive after construction, we are ready to get rid of the deferred commands
+                    this.m_deferredCommands = null;
+                    // We are fully initialized, do the command 
                     DoCommand(commandArgs);
+                }
                 else
                 {
                     // We can't do the command, simply remember it and we do it when we are fully constructed.  
@@ -2603,9 +2723,12 @@ namespace System.Diagnostics.Tracing
                         Contract.Assert(m_eventData != null);
                         m_eventSourceEnabled = true;
                     }
-
+                    
                     this.OnEventCommand(commandArgs);
-
+                    var eventCommandCallback = this.m_eventCommandExecuted;
+                    if (eventCommandCallback != null)
+                        eventCommandCallback(this, commandArgs);
+                    
 #if FEATURE_ACTIVITYSAMPLING
                     if (commandArgs.listener == null && !bSessionEnable && commandArgs.perEventSourceSessionId != -1)
                     {
@@ -2688,8 +2811,11 @@ namespace System.Diagnostics.Tracing
                     // Contract.Assert(enable == true);
                     // Contract.Assert(level == EventLevel.LogAlways);
                     // Contract.Assert(matchAnyKeyword == EventKeywords.None);
-
+                    
                     this.OnEventCommand(commandArgs);
+                    var eventCommandCallback = m_eventCommandExecuted;
+                    if (eventCommandCallback != null)
+                        eventCommandCallback(this, commandArgs);
                 }
 
 #if FEATURE_ACTIVITYSAMPLING
@@ -2976,7 +3102,7 @@ namespace System.Diagnostics.Tracing
                             }
                             success = false;
                             if (ThrowOnEventWriteErrors)
-                                ThrowEventSourceException();
+                                ThrowEventSourceException("SendManifest");
                             break;
                         }
                     }
@@ -3213,7 +3339,7 @@ namespace System.Diagnostics.Tracing
                     manifest.AddKeyword("Session0", (long)0x8000 << 32);
                 }
 
-                if (eventSourceType.Name != "EventSource")
+                if (eventSourceType != typeof(EventSource))
                 {
                     for (int i = 0; i < methods.Length; i++)
                     {
@@ -3222,6 +3348,20 @@ namespace System.Diagnostics.Tracing
 
                         // Get the EventDescriptor (from the Custom attributes)
                         EventAttribute eventAttribute = (EventAttribute)GetCustomAttributeHelper(method, typeof(EventAttribute), flags);
+                        
+                        // Visual Studio online bug #222067 - we can't add a dependency in System.Web on EventSource features that 
+                        // didn't exist in 4.5. We have to manually set the disable flag here since the ActivityOptions 
+                        // falls in to that category.
+                        // 
+                        // The check for <= 3 is to only disable Activity tracking for the RequestStarted and RequestCompleted
+                        // events. 
+                        if (eventAttribute != null
+                            && source != null
+                            && eventAttribute.EventId <= 3
+                            && source.Guid.Equals(AspNetEventSourceGuid))
+                        {
+                            eventAttribute.ActivityOptions |= EventActivityOptions.Disable;
+                        }
 
                         // Compat: until v4.5.1 we ignored any non-void returning methods as well as virtual methods for 
                         // the only reason of limiting the number of methods considered to be events. This broke a common 
@@ -3273,15 +3413,17 @@ namespace System.Diagnostics.Tracing
                         eventId++;
                         string eventName = method.Name;
 
-                        if (!eventAttribute.IsOpcodeSet)
+                        if (eventAttribute.Opcode == EventOpcode.Info)      // We are still using the default opcode. 
                         {
                             // By default pick a task ID derived from the EventID, starting with the highest task number and working back 
                             bool noTask = (eventAttribute.Task == EventTask.None);
-                            if (eventAttribute.Task == EventTask.None)
+                            if (noTask)
                                 eventAttribute.Task = (EventTask)(0xFFFE - eventAttribute.EventId);
 
-                            // pick a default opcode (either Info or start or stop if the name ends with that suffix.  
-                            eventAttribute.Opcode = GetOpcodeWithDefault(EventOpcode.Info, eventName);
+                            // Unless we explicitly set the opcode to Info (to override the auto-generate of Start or Stop opcodes, 
+                            // pick a default opcode based on the event name (either Info or start or stop if the name ends with that suffix).  
+                            if (!eventAttribute.IsOpcodeSet)
+                                eventAttribute.Opcode = GetOpcodeWithDefault(EventOpcode.Info, eventName);
 
                             // Make the stop opcode have the same task as the start opcode.
                             if (noTask)
@@ -3299,7 +3441,7 @@ namespace System.Diagnostics.Tracing
                                 }
                                 else if (eventAttribute.Opcode == EventOpcode.Stop)
                                 {
-                                    // Find the start associated with this stop event.  We require start to be immediately before the stop
+                                    // Find the start associated with this stop event.  We requre start to be immediately before the stop
                                     int startEventId = eventAttribute.EventId - 1;
                                     if (eventData != null && startEventId < eventData.Length)    
                                     {
@@ -3325,7 +3467,7 @@ namespace System.Diagnostics.Tracing
                             }
                         }
 
-                        RemoveFirstArgIfRelatedActivityId(ref args);
+                        bool hasRelatedActivityID = RemoveFirstArgIfRelatedActivityId(ref args);
                         if (!(source != null && source.SelfDescribingEvents))
                         {
                             manifest.StartEvent(eventName, eventAttribute);
@@ -3339,7 +3481,7 @@ namespace System.Diagnostics.Tracing
                         if (source != null || (flags & EventManifestOptions.Strict) != 0)
                         {
                             // Do checking for user errors (optional, but not a big deal so we do it).  
-                            DebugCheckEvent(ref eventsByName, eventData, method, eventAttribute, manifest);
+                            DebugCheckEvent(ref eventsByName, eventData, method, eventAttribute, manifest, flags);
 
 #if FEATURE_MANAGED_ETW_CHANNELS
                             // add the channel keyword for Event Viewer channel based filters. This is added for creating the EventDescriptors only
@@ -3357,7 +3499,7 @@ namespace System.Diagnostics.Tracing
                             // overwrite inline message with the localized message
                             if (msg != null) eventAttribute.Message = msg;
 
-                            AddEventDescriptor(ref eventData, eventName, eventAttribute, args);
+                            AddEventDescriptor(ref eventData, eventName, eventAttribute, args, hasRelatedActivityID);
                         }
                     }
                 }
@@ -3379,7 +3521,7 @@ namespace System.Diagnostics.Tracing
                 {
                     bNeedsManifest = (flags & EventManifestOptions.OnlyIfNeededForRegistration) == 0
 #if FEATURE_MANAGED_ETW_CHANNELS
                                           || manifest.GetChannelData().Length > 0
+ || manifest.GetChannelData().Length > 0
 #endif
 ;
 
@@ -3422,7 +3564,7 @@ namespace System.Diagnostics.Tracing
             return bNeedsManifest ? res : null;
         }
 
-        private static void RemoveFirstArgIfRelatedActivityId(ref ParameterInfo[] args)
+        private static bool RemoveFirstArgIfRelatedActivityId(ref ParameterInfo[] args)
         {
             // If the first parameter is (case insensitive) 'relatedActivityId' then skip it.  
             if (args.Length > 0 && args[0].ParameterType == typeof(Guid) &&
@@ -3431,7 +3573,11 @@ namespace System.Diagnostics.Tracing
                 var newargs = new ParameterInfo[args.Length - 1];
                 Array.Copy(args, 1, newargs, 0, args.Length - 1);
                 args = newargs;
+
+                return true;
             }
+            
+            return false;
         }
 
         // adds a enumeration (keyword, opcode, task or channel) represented by 'staticField'
@@ -3475,7 +3621,8 @@ namespace System.Diagnostics.Tracing
         // with the code:EventAttribute 'eventAttribute'.  resourceManger may be null in which case we populate it
         // it is populated if we need to look up message resources
         private static void AddEventDescriptor(ref EventMetadata[] eventData, string eventName,
-                                EventAttribute eventAttribute, ParameterInfo[] eventParameters)
+                                EventAttribute eventAttribute, ParameterInfo[] eventParameters,
+                                bool hasRelatedActivityID)
         {
             if (eventData == null || eventData.Length <= eventAttribute.EventId)
             {
@@ -3488,7 +3635,7 @@ namespace System.Diagnostics.Tracing
                     eventAttribute.EventId,
                     eventAttribute.Version,
 #if FEATURE_MANAGED_ETW_CHANNELS
                   (byte)eventAttribute.Channel,
+ (byte)eventAttribute.Channel,
 #else
  (byte)0,
 #endif
@@ -3502,6 +3649,7 @@ namespace System.Diagnostics.Tracing
             eventData[eventAttribute.EventId].Parameters = eventParameters;
             eventData[eventAttribute.EventId].Message = eventAttribute.Message;
             eventData[eventAttribute.EventId].ActivityOptions = eventAttribute.ActivityOptions;
+            eventData[eventAttribute.EventId].HasRelatedActivityID = hasRelatedActivityID;
         }
 
         // Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct
@@ -3541,7 +3689,7 @@ namespace System.Diagnostics.Tracing
         // index for two distinct events etc.  Throws exceptions when it finds something wrong. 
         private static void DebugCheckEvent(ref Dictionary<string, string> eventsByName,
             EventMetadata[] eventData, MethodInfo method, EventAttribute eventAttribute,
-            ManifestBuilder manifest)
+            ManifestBuilder manifest, EventManifestOptions options)
         {
             int evtId = eventAttribute.EventId;
             string evtName = method.Name;
@@ -3568,14 +3716,30 @@ namespace System.Diagnostics.Tracing
                 {
                     manifest.ManifestError(Environment.GetResourceString("EventSource_TaskOpcodePairReused",
                                             evtName, evtId, eventData[idx].Name, idx));
+
+                    // If we are not strict stop on first error.   We have had problems with really large providers taking forever.  because of many errors.  
+                    if ((options & EventManifestOptions.Strict) == 0)
+                        break;
                 }
             }
 
             // for non-default event opcodes the user must define a task!
-            if (eventAttribute.Opcode != EventOpcode.Info &&
-                (eventAttribute.Task == EventTask.None || eventAttribute.Task == (EventTask)(0xFFFE - evtId)))
+            if (eventAttribute.Opcode != EventOpcode.Info)
             {
-                manifest.ManifestError(Environment.GetResourceString("EventSource_EventMustHaveTaskIfNonDefaultOpcode", evtName, evtId));
+                bool failure = false;
+                if (eventAttribute.Task == EventTask.None)
+                    failure = true;
+                else
+                {
+                    // If you have the auto-assigned Task, then you did not explicitly set one.  
+                    // This is OK for Start events because we have special logic to assign the task to a prefix derived from the event name
+                    // But all other cases we want to catch the omission.  
+                    var autoAssignedTask = (EventTask)(0xFFFE - evtId);
+                    if ((eventAttribute.Opcode != EventOpcode.Start && eventAttribute.Opcode != EventOpcode.Stop) && eventAttribute.Task == autoAssignedTask)
+                        failure = true;
+                }
+                if (failure)
+                    manifest.ManifestError(Environment.GetResourceString("EventSource_EventMustHaveTaskIfNonDefaultOpcode", evtName, evtId));
             }
 
             // If we ever want to enforce the rule: MethodName = TaskName + OpcodeName here's how:
@@ -3591,7 +3755,7 @@ namespace System.Diagnostics.Tracing
                 eventsByName = new Dictionary<string, string>();
 
             if (eventsByName.ContainsKey(evtName))
-                manifest.ManifestError(Environment.GetResourceString("EventSource_EventNameReused", evtName));
+                manifest.ManifestError(Environment.GetResourceString("EventSource_EventNameReused", evtName), true);
 
             eventsByName[evtName] = evtName;
         }
@@ -3759,13 +3923,13 @@ namespace System.Diagnostics.Tracing
 #endif
 
                 // Send it to all listeners.
-                if (m_outOfBandMessageCount < 254)     // Note this is only if size byte
+                if (m_outOfBandMessageCount < 16-1)     // Note this is only if size byte
                     m_outOfBandMessageCount++;
                 else
                 {
-                    if (m_outOfBandMessageCount == 255)
+                    if (m_outOfBandMessageCount == 16)
                         return;
-                    m_outOfBandMessageCount = 255;    // Mark that we hit the limit.  Notify them that this is the case. 
+                    m_outOfBandMessageCount = 16;    // Mark that we hit the limit.  Notify them that this is the case. 
                     msg = "Reached message limit.   End of EventSource error messages.";
                 }
 
@@ -3870,6 +4034,8 @@ namespace System.Diagnostics.Tracing
         internal volatile EventMetadata[] m_eventData;  // None per-event data
         private volatile byte[] m_rawManifest;          // Bytes to send out representing the event schema
 
+        private EventHandler<EventCommandEventArgs> m_eventCommandExecuted;
+
         private EventSourceSettings m_config;      // configuration information
 
         // Enabling bits
@@ -3919,6 +4085,10 @@ namespace System.Diagnostics.Tracing
             0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
         };
 
+        // Visual Studio Online 222067 - This is only needed for a compatibility hack. We need to check to see
+        // if an EventSource is the AspNetEventSource to override the ActivityTracking for it. 
+        private static readonly Guid AspNetEventSourceGuid = new Guid("ee799f41-cfa5-550b-bf2c-344747c1c668");
+        
         #endregion
     }
 
@@ -3990,52 +4160,60 @@ namespace System.Diagnostics.Tracing
     /// created.
     /// </para>
     /// </summary>
-    public abstract class EventListener : IDisposable
+    public class EventListener : IDisposable
     {
+        private static readonly object s_EventSourceCreatedLock = new object();
+        
+        private event EventHandler<EventSourceCreatedEventArgs> _EventSourceCreated;
+
         /// <summary>
-        /// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
-        /// them on).  
+        /// This event is raised whenever a new eventSource is 'attached' to the dispatcher.
+        /// This can happen for all existing EventSources when the EventListener is created
+        /// as well as for any EventSources that come into existence after the EventListener
+        /// has been created.
+        /// 
+        /// These 'catch up' events are called during the construction of the EventListener.
+        /// Subclasses need to be prepared for that.
+        /// 
+        /// In a multi-threaded environment, it is possible that 'EventSourceEventWrittenCallback' 
+        /// events for a particular eventSource to occur BEFORE the EventSourceCreatedCallback is issued.
         /// </summary>
-        protected EventListener()
-        {
-            lock (EventListenersLock)
+        public event EventHandler<EventSourceCreatedEventArgs> EventSourceCreated
+        { 
+            add
             {
-                // Disallow creating EventListener reentrancy. 
-                if (s_CreatingListener)
-                    throw new InvalidOperationException(Environment.GetResourceString("EventSource_ListenerCreatedInsideCallback"));
-
-                try
+                lock (s_EventSourceCreatedLock)
                 {
-                    s_CreatingListener = true;
-
-                    // Add to list of listeners in the system, do this BEFORE firing the 'OnEventSourceCreated' so that 
-                    // Those added sources see this listener.
-                    this.m_Next = s_Listeners;
-                    s_Listeners = this;
-
-                    // Find all existing eventSources call OnEventSourceCreated to 'catchup'
-                    // Note that we DO have reentrancy here because 'AddListener' calls out to user code (via OnEventSourceCreated callback) 
-                    // We tolerate this by iterating over a copy of the list here. New event sources will take care of adding listeners themselves
-                    // EventSources are not guaranteed to be added at the end of the s_EventSource list -- We re-use slots when a new source
-                    // is created.
-                    WeakReference[] eventSourcesSnapshot = s_EventSources.ToArray();
-
-                    for (int i = 0; i < eventSourcesSnapshot.Length; i++)
-                    {
-                        WeakReference eventSourceRef = eventSourcesSnapshot[i];
-                        EventSource eventSource = eventSourceRef.Target as EventSource;
-                        if (eventSource != null)
-                            eventSource.AddListener(this); // This will cause the OnEventSourceCreated callback to fire. 
-                    }
+                    CallBackForExistingEventSources(false, value);
 
-                    Validate();
+                    this._EventSourceCreated = (EventHandler<EventSourceCreatedEventArgs>)Delegate.Combine(_EventSourceCreated, value);
                 }
-                finally
+            }
+            remove
+            {
+                lock (s_EventSourceCreatedLock)
                 {
-                    s_CreatingListener = false;
+                    this._EventSourceCreated = (EventHandler<EventSourceCreatedEventArgs>)Delegate.Remove(_EventSourceCreated, value);
                 }
             }
         }
+
+        /// <summary>
+        /// This event is raised whenever an event has been written by a EventSource for which 
+        /// the EventListener has enabled events.  
+        /// </summary>
+        public event EventHandler<EventWrittenEventArgs> EventWritten;
+
+        /// <summary>
+        /// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
+        /// them on).  
+        /// </summary>
+        public EventListener()
+        {
+            // This will cause the OnEventSourceCreated callback to fire. 
+            CallBackForExistingEventSources(true, (obj, args) => args.EventSource.AddListener(this) ); 
+        }
+        
         /// <summary>
         /// Dispose should be called when the EventListener no longer desires 'OnEvent*' callbacks. Because
         /// there is an internal list of strong references to all EventListeners, calling 'Dispose' directly
@@ -4164,12 +4342,31 @@ 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) { }
+        internal protected virtual void OnEventSourceCreated(EventSource eventSource)
+        {
+            EventHandler<EventSourceCreatedEventArgs> callBack = this._EventSourceCreated;
+            if(callBack != null)
+            {
+                EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
+                args.EventSource = eventSource;
+                callBack(this, args);
+            }
+        }
+        
         /// <summary>
         /// This method is called whenever an event has been written by a EventSource for which 
         /// the EventListener has enabled events.  
         /// </summary>
-        internal protected abstract void OnEventWritten(EventWrittenEventArgs eventData);
+        /// <param name="eventData"></param>
+        internal protected virtual void OnEventWritten(EventWrittenEventArgs eventData)
+        {
+            EventHandler<EventWrittenEventArgs> callBack = this.EventWritten;
+            if (callBack != null)
+            {
+                callBack(this, eventData);
+            }
+        }
+
         /// <summary>
         /// EventSourceIndex is small non-negative integer (suitable for indexing in an array)
         /// identifying EventSource. It is unique per-appdomain. Some EventListeners might find
@@ -4251,11 +4448,14 @@ namespace System.Diagnostics.Tracing
         // See bug 724140 for more
         private static void DisposeOnShutdown(object sender, EventArgs e)
         {
-            foreach (var esRef in s_EventSources)
+            lock(EventListenersLock)
             {
-                EventSource es = esRef.Target as EventSource;
-                if (es != null)
-                    es.Dispose();
+                foreach (var esRef in s_EventSources)
+                {
+                    EventSource es = esRef.Target as EventSource;
+                    if (es != null)
+                        es.Dispose();
+                }
             }
         }
 
@@ -4267,6 +4467,9 @@ namespace System.Diagnostics.Tracing
         /// </summary>
         private static void RemoveReferencesToListenerInEventSources(EventListener listenerToRemove)
         {
+#if !ES_BUILD_STANDALONE
+            Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock));
+#endif
             // Foreach existing EventSource in the appdomain
             foreach (WeakReference eventSourceRef in s_EventSources)
             {
@@ -4365,6 +4568,55 @@ namespace System.Diagnostics.Tracing
                 return s_EventSources;
             }
         }
+        
+        private void CallBackForExistingEventSources(bool addToListenersList, EventHandler<EventSourceCreatedEventArgs> callback)
+        {
+            lock (EventListenersLock)
+            {
+                // Disallow creating EventListener reentrancy. 
+                if (s_CreatingListener)
+                    throw new InvalidOperationException(Environment.GetResourceString("EventSource_ListenerCreatedInsideCallback"));
+
+                try
+                {
+                    s_CreatingListener = true;
+
+                    if (addToListenersList)
+                    {
+                        // Add to list of listeners in the system, do this BEFORE firing the 'OnEventSourceCreated' so that 
+                        // Those added sources see this listener.
+                        this.m_Next = s_Listeners;
+                        s_Listeners = this;
+                    }
+
+                    // Find all existing eventSources call OnEventSourceCreated to 'catchup'
+                    // Note that we DO have reentrancy here because 'AddListener' calls out to user code (via OnEventSourceCreated callback) 
+                    // We tolerate this by iterating over a copy of the list here. New event sources will take care of adding listeners themselves
+                    // EventSources are not guaranteed to be added at the end of the s_EventSource list -- We re-use slots when a new source
+                    // is created.
+                    WeakReference[] eventSourcesSnapshot = s_EventSources.ToArray();
+
+                    for (int i = 0; i < eventSourcesSnapshot.Length; i++)
+                    {
+                        WeakReference eventSourceRef = eventSourcesSnapshot[i];
+                        EventSource eventSource = eventSourceRef.Target as EventSource;
+                        if (eventSource != null)
+                        {
+                            EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
+                            args.EventSource = eventSource;
+                            callback(this, args);
+                        }
+                    }
+
+                    Validate();
+                }
+                finally
+                {
+                    s_CreatingListener = false;
+                }
+            }
+
+        }
 
         // Instance fields
         internal volatile EventListener m_Next;                         // These form a linked list in s_Listeners
@@ -4469,6 +4721,21 @@ namespace System.Diagnostics.Tracing
         #endregion
     }
 
+    /// <summary>
+    /// EventSourceCreatedEventArgs is passed to <see cref="EventListener.EventSourceCreated"/>
+    /// </summary>
+    public class EventSourceCreatedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// The EventSource that is attaching to the listener.
+        /// </summary>
+        public EventSource EventSource
+        {
+            get;
+            internal set;
+        }
+    }
+
     /// <summary>
     /// EventWrittenEventArgs is passed to the user-provided override for
     /// <see cref="EventListener.OnEventWritten"/> when an event is fired.
@@ -5291,7 +5558,7 @@ namespace System.Diagnostics.Tracing
             }
         }
 
-        #region private
+    #region private
 
         /// <summary>
         /// Creates a new ActivityFilter that is triggered by 'eventId' from 'source' ever
@@ -5460,7 +5727,7 @@ namespace System.Diagnostics.Tracing
 
         ActivityFilter m_next;      // We create a linked list of these
         Action<Guid> m_myActivityDelegate;
-        #endregion
+    #endregion
     };
 
 
@@ -6212,8 +6479,8 @@ namespace System.Diagnostics.Tracing
                 cultures.Add(CultureInfo.CurrentUICulture);
             }
 #if ES_BUILD_STANDALONE
-                var sortedStrings = new List<string>(stringTab.Keys);
-                sortedStrings.Sort();
+            var sortedStrings = new List<string>(stringTab.Keys);
+            sortedStrings.Sort();
 #else
             // DD 947936
             var sortedStrings = new string[stringTab.Keys.Count];
@@ -6264,10 +6531,13 @@ namespace System.Diagnostics.Tracing
 
             stringBuilder.Append(" message=\"$(string.").Append(key).Append(")\"");
             string prevValue;
-            if (stringTab.TryGetValue(key, out prevValue))
+            if (stringTab.TryGetValue(key, out prevValue) && !prevValue.Equals(value))
+            {
                 ManifestError(Environment.GetResourceString("EventSource_DuplicateStringKey", key), true);
-            else
-                stringTab.Add(key, value);
+                return;
+            }
+
+            stringTab[key] = value;
         }
         internal string GetLocalizedMessage(string key, CultureInfo ci, bool etwFormat)
         {
@@ -6331,7 +6601,7 @@ namespace System.Diagnostics.Tracing
                 // rest get names Channel<N>.  This allows users to modify the Manifest if they want more advanced features. 
                 if (channelTab == null)
                     channelTab = new Dictionary<int, ChannelInfo>(4);
-                
+
                 string channelName = channel.ToString();        // For well know channels this is a nice name, otherwise a number 
                 if (EventChannel.Debug < channel)
                     channelName = "Channel" + channelName;      // Add a 'Channel' prefix for numbers.  
index 5e9b986bd7bc2cf44a807d73fc62271aa1e881e0..d5feefac388553eda4eec53ac90133e6e97a62dc 100644 (file)
@@ -416,7 +416,7 @@ namespace System {
                 
 #if !FEATURE_CORECLR
                 // Do security check
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, path);
 #endif
 
                 return path;
index 45b0322f8ce8292c5e1cac8024ab24eb39e728b0..e2f2f3055e5506bc36f92f97269249c6ea2c7ab4 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Globalization {
     **      Gregorian   1912/01/01  9999/12/31
     **      Taiwan      01/01/01    8088/12/31
     ============================================================================*/
-
+  
 
     [System.Runtime.InteropServices.ComVisible(true)]
     [Serializable] public class TaiwanCalendar: Calendar {
index e318533937add8f2b4d6daf84e59f23d4888e72e..a7a35c642dd72c828c65dae9fbb83ce5fd061bcb 100644 (file)
@@ -79,29 +79,21 @@ namespace System.IO {
         [System.Security.SecurityCritical]  // auto-generated
         internal static String GetDisplayablePath(String path, bool isInvalidPath)
         {
-            
             if (String.IsNullOrEmpty(path))
                 return String.Empty;
 
-            // Is it a fully qualified path?
-            bool isFullyQualified = false;
             if (path.Length < 2)
                 return path;
-            if (Path.IsDirectorySeparator(path[0]) && Path.IsDirectorySeparator(path[1]))
-                isFullyQualified = true;
-            else if (path[1] == Path.VolumeSeparatorChar) {
-                isFullyQualified = true;
-            }
 
-            if (!isFullyQualified && !isInvalidPath)
+            // Return the path as is if we're relative (not fully qualified) and not a bad path
+            if (PathInternal.IsPartiallyQualified(path) && !isInvalidPath)
                 return path;
 
-#if FEATURE_MONO_CAS
             bool safeToReturn = false;
             try {
                 if (!isInvalidPath) {
-#if !FEATURE_CORECLR
-                    new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand();
+#if !FEATURE_CORECLR && FEATURE_MONO_CAS
+                    FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, path, false, false);
 #endif
                     safeToReturn = true;
                 }
@@ -117,9 +109,7 @@ namespace System.IO {
                 // from Security.Util.StringExpressionSet.CanonicalizePath when ':' is found in the path
                 // beyond string index position 1.  
             }
-#else
-            bool safeToReturn = !isInvalidPath;
-#endif // FEATURE_MONO_CAS
+            
             if (!safeToReturn) {
                 if (Path.IsDirectorySeparator(path[path.Length - 1]))
                     path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName");
index 409b35c3772ee94c735d385805ffb816f1b5f1f7..3357589278655c7731f6f5c03311a88d15a26e31 100644 (file)
@@ -382,10 +382,23 @@ namespace System.IO {
                 }
 
                 Contract.Assert(byteBuffer != null, "expected byteBuffer to be non-null");
-                unsafe {
-                    fixed (byte* pBytes = byteBuffer)
-                    fixed (char* pChars = buffer) {
-                        charsRead = m_decoder.GetChars(pBytes + position, numBytes, pChars + index, charsRemaining, false);
+
+                checked { 
+
+                    if (position < 0 || numBytes < 0 || position + numBytes > byteBuffer.Length) {
+                        throw new ArgumentOutOfRangeException("byteCount");
+                    }
+
+                    if (index < 0 || charsRemaining < 0 || index + charsRemaining > buffer.Length) {
+                       throw new ArgumentOutOfRangeException("charsRemaining");
+                    }
+
+                    unsafe {
+                        fixed (byte* pBytes = byteBuffer) {
+                            fixed (char* pChars = buffer) {
+                                charsRead = m_decoder.GetChars(pBytes + position, numBytes, pChars + index, charsRemaining, false);
+                            }
+                        }
                     }
                 }
 
index ad11daa8bdf366fd9380d14b248325d45cc534f1..c6f81955e43a1a1b6225262f35862d9f61e372e1 100644 (file)
@@ -196,7 +196,7 @@ namespace System.IO {
             Contract.Assert(_encoding.GetMaxByteCount(1) <= 16, "_encoding.GetMaxByteCount(1) <= 16)");
             int numBytes = 0;
             fixed(byte * pBytes = _buffer) {
-                numBytes = _encoder.GetBytes(&ch, 1, pBytes, 16, true);
+                numBytes = _encoder.GetBytes(&ch, 1, pBytes, _buffer.Length, true);
             }
             OutStream.Write(_buffer, 0, numBytes);
         }
@@ -371,10 +371,10 @@ namespace System.IO {
 
             if (_largeByteBuffer == null) {
                 _largeByteBuffer = new byte[LargeByteBufferSize];
-                _maxChars = LargeByteBufferSize / _encoding.GetMaxByteCount(1);
+                _maxChars = _largeByteBuffer.Length / _encoding.GetMaxByteCount(1);
             }
 
-            if (len <= LargeByteBufferSize) {
+            if (len <= _largeByteBuffer.Length) {
                 //Contract.Assert(len == _encoding.GetBytes(chars, 0, chars.Length, _largeByteBuffer, 0), "encoding's GetByteCount & GetBytes gave different answers!  encoding type: "+_encoding.GetType().Name);
                 _encoding.GetBytes(value, 0, value.Length, _largeByteBuffer, 0);
                 OutStream.Write(_largeByteBuffer, 0, len);
@@ -393,14 +393,21 @@ namespace System.IO {
                     // Figure out how many chars to process this round.
                     int charCount = (numLeft > _maxChars) ? _maxChars : numLeft;
                     int byteLen;
-                    fixed(char* pChars = value) {
-                        fixed(byte* pBytes = _largeByteBuffer) {
-                            byteLen = _encoder.GetBytes(pChars + charStart, charCount, pBytes, LargeByteBufferSize, charCount == numLeft);
+
+                    checked {
+                        if (charStart < 0 || charCount < 0 || charStart + charCount > value.Length) {
+                            throw new ArgumentOutOfRangeException("charCount");
+                        }
+
+                        fixed(char* pChars = value) {
+                            fixed(byte* pBytes = _largeByteBuffer) {
+                                byteLen = _encoder.GetBytes(pChars + charStart, charCount, pBytes, _largeByteBuffer.Length, charCount == numLeft);
+                            }
                         }
                     }
 #if _DEBUG
                     totalBytes += byteLen;
-                    Contract.Assert (totalBytes <= len && byteLen <= LargeByteBufferSize, "BinaryWriter::Write(String) - More bytes encoded than expected!");
+                    Contract.Assert (totalBytes <= len && byteLen <= _largeByteBuffer.Length, "BinaryWriter::Write(String) - More bytes encoded than expected!");
 #endif
                     OutStream.Write(_largeByteBuffer, 0, byteLen);
                     charStart += charCount;
index da6f5ab57e45afc6f7e50f02af951f214e001202..943e8ff52b939eb70420358c0cd1e163d1cfe18a 100644 (file)
@@ -248,17 +248,25 @@ namespace System.IO {
 
             int count = stackDir.Count;
 
-            if (stackDir.Count != 0)
+            if (stackDir.Count != 0
+#if FEATURE_CAS_POLICY
+                // All demands in full trust domains are no-ops, so skip
+                //
+                // The full path went through validity checks by being passed through FileIOPermissions already.
+                // As a sub string of the full path can't fail the checks if the full path passes.
+                && !CodeAccessSecurityEngine.QuickCheckForAllDemands()
+#endif
+            )
             {
-                String [] securityList = new String[stackDir.Count];
+                String[] securityList = new String[stackDir.Count];
                 stackDir.CopyTo(securityList, 0);
                 for (int j = 0 ; j < securityList.Length; j++)
                     securityList[j] += "\\."; // leaf will never have a slash at the end
 
                 // Security check for all directories not present only.
-#if !FEATURE_PAL  && FEATURE_MACL
+#if !FEATURE_PAL && FEATURE_MACL
                 AccessControlActions control = (dirSecurity == null) ? AccessControlActions.None : AccessControlActions.Change;
-                new FileIOPermission(FileIOPermissionAccess.Write, control, securityList, false, false ).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, control, securityList, false, false);
 #else
 #if FEATURE_CORECLR
                 if (checkHost)
@@ -270,7 +278,7 @@ namespace System.IO {
                     }
                 }
 #else
-                new FileIOPermission(FileIOPermissionAccess.Write, securityList, false, false ).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, securityList, false, false );
 #endif
 #endif //!FEATURE_PAL  && FEATURE_MACL
             }
@@ -298,8 +306,9 @@ namespace System.IO {
             while (stackDir.Count > 0) {
                 String name = stackDir[stackDir.Count - 1];
                 stackDir.RemoveAt(stackDir.Count - 1);
-                if (name.Length >= Path.MAX_DIRECTORY_PATH)
+                if (PathInternal.IsDirectoryTooLong(name))
                     throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
                 r = Win32Native.CreateDirectory(name, secAttrs);
                 if (!r && (firstError == 0)) {
                     int currentError = Marshal.GetLastWin32Error();
@@ -326,7 +335,7 @@ namespace System.IO {
                                     state.EnsureState();
                                 }
 #else
-                                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true)).Demand();
+                                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true));
 #endif // FEATURE_CORECLR
                                 errorString = name;
                             }
@@ -1085,49 +1094,88 @@ namespace System.IO {
             return InternalGetCurrentDirectory(false);
         }
 
+        [System.Security.SecuritySafeCritical]
+        [ResourceExposure(ResourceScope.Machine)]
+        [ResourceConsumption(ResourceScope.Machine)]
+        private static string InternalGetCurrentDirectory(bool checkHost)
+        {
+            string currentDirectory = AppContextSwitches.UseLegacyPathHandling ? LegacyGetCurrentDirectory() : NewGetCurrentDirectory();
+            string demandPath = GetDemandDir(currentDirectory, true);
+
+#if FEATURE_CORECLR
+            if (checkHost) 
+            {
+                FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath);
+                state.EnsureState();
+            }
+#else
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPath, false, false);
+#endif
+            return currentDirectory;
+        }
+
         [System.Security.SecurityCritical]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        private static String InternalGetCurrentDirectory(bool checkHost)
+        private static string LegacyGetCurrentDirectory()
         {
-            StringBuilder sb = StringBuilderCache.Acquire(Path.MAX_PATH + 1);
+            StringBuilder sb = StringBuilderCache.Acquire(PathInternal.MaxShortPath + 1);
             if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0)
                 __Error.WinIOError();
-            String currentDirectory = sb.ToString();
+            string currentDirectory = sb.ToString();
             // Note that if we have somehow put our command prompt into short
             // file name mode (ie, by running edlin or a DOS grep, etc), then
             // this will return a short file name.
-            if (currentDirectory.IndexOf('~') >= 0) {
+            if (currentDirectory.IndexOf('~') >= 0)
+            {
                 int r = Win32Native.GetLongPathName(currentDirectory, sb, sb.Capacity);
-                if (r == 0 || r >= Path.MAX_PATH) {                    
+                if (r == 0 || r >= PathInternal.MaxShortPath)
+                {
                     int errorCode = Marshal.GetLastWin32Error();
-                    if (r >= Path.MAX_PATH)
+                    if (r >= PathInternal.MaxShortPath)
                         errorCode = Win32Native.ERROR_FILENAME_EXCED_RANGE;
                     if (errorCode != Win32Native.ERROR_FILE_NOT_FOUND &&
                         errorCode != Win32Native.ERROR_PATH_NOT_FOUND &&
                         errorCode != Win32Native.ERROR_INVALID_FUNCTION &&  // by design - enough said.
                         errorCode != Win32Native.ERROR_ACCESS_DENIED)
-                        __Error.WinIOError(errorCode, String.Empty);
+                        __Error.WinIOError(errorCode, string.Empty);
                 }
                 currentDirectory = sb.ToString();
             }
             StringBuilderCache.Release(sb);
-            String demandPath = GetDemandDir(currentDirectory, true);
+            return currentDirectory;
+        }
 
-            
-#if FEATURE_CORECLR
-            if (checkHost) 
+        [System.Security.SecurityCritical]
+        [ResourceExposure(ResourceScope.Machine)]
+        [ResourceConsumption(ResourceScope.Machine)]
+        private static string NewGetCurrentDirectory()
+        {
+            using (StringBuffer buffer = new StringBuffer(PathInternal.MaxShortPath))
             {
-                FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath);
-                state.EnsureState();
+                uint result = 0;
+                while ((result = Win32Native.GetCurrentDirectoryW(buffer.CharCapacity, buffer.GetHandle())) > buffer.CharCapacity)
+                {
+                    // Reported size is greater than the buffer size. Increase the capacity.
+                    // The size returned includes the null only if more space is needed (this case).
+                    buffer.EnsureCharCapacity(result);
+                }
+
+                if (result == 0)
+                {
+                    __Error.WinIOError();
+                }
+
+                buffer.Length = result;
+                if (buffer.Contains('~'))
+                {
+                    return LongPathHelper.GetLongPathName(buffer);
+                }
+
+                return buffer.ToString();
             }
-#else
-            new FileIOPermission( FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false ).Demand();
-#endif
-            return currentDirectory;
         }
 
-
         #if FEATURE_CORECLR
         [System.Security.SecurityCritical] // auto-generated
         #else
@@ -1136,15 +1184,16 @@ namespace System.IO {
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
         public static void SetCurrentDirectory(String path)
-        {        
+        {
             if (path==null)
                 throw new ArgumentNullException("value");
             if (path.Length==0)
                 throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"));
             Contract.EndContractBlock();
-            if (path.Length >= Path.MAX_PATH)
+
+            if (PathInternal.IsPathTooLong(path))
                 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
-                
+
             // This will have some large effects on the rest of the runtime
             // and other appdomains in this process.  Demand unmanaged code.
 #pragma warning disable 618
@@ -1174,19 +1223,19 @@ namespace System.IO {
         [System.Security.SecurityCritical]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        internal static void UnsafeMove(String sourceDirName,String destDirName) {
+        internal static void UnsafeMove(String sourceDirName, String destDirName) {
             InternalMove(sourceDirName, destDirName, false);
         }
 
         [System.Security.SecurityCritical]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        private static void InternalMove(String sourceDirName,String destDirName,bool checkHost) {
+        private static void InternalMove(String sourceDirName, String destDirName, bool checkHost) {
             if (sourceDirName==null)
                 throw new ArgumentNullException("sourceDirName");
             if (sourceDirName.Length==0)
                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceDirName");
-            
+
             if (destDirName==null)
                 throw new ArgumentNullException("destDirName");
             if (destDirName.Length==0)
@@ -1195,16 +1244,16 @@ namespace System.IO {
 
             String fullsourceDirName = Path.GetFullPathInternal(sourceDirName);
             String sourcePath = GetDemandDir(fullsourceDirName, false);
-            
-            if (sourcePath.Length >= Path.MAX_DIRECTORY_PATH)
+
+            if (PathInternal.IsDirectoryTooLong(sourcePath))
                 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
 
             String fulldestDirName = Path.GetFullPathInternal(destDirName);
             String destPath = GetDemandDir(fulldestDirName, false);
 
-            if (destPath.Length >= Path.MAX_DIRECTORY_PATH)
+            if (PathInternal.IsDirectoryTooLong(sourcePath))
                 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
-            
+
 #if FEATURE_CORECLR
             if (checkHost) {
                 FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, sourceDirName, sourcePath);
@@ -1288,7 +1337,7 @@ namespace System.IO {
             }
 #else
             // Make sure we have write permission to this directory
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandPath }, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, demandPath, false, false);
 #endif
 
             // Do not recursively delete through reparse points.  Perhaps in a 
index 5d88346dd312387436ce70db911f7522c5bb1562..4a5d733a5fc3cb7a9298ddc1fc8ceba95b6e136d 100644 (file)
@@ -102,7 +102,7 @@ namespace System.IO {
                 state.EnsureState();
             }
 #else
-            new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false);
 #endif
 
             FullPath = fullPath;
@@ -130,7 +130,7 @@ namespace System.IO {
         {
 #if !FEATURE_CORECLR
             demandDir = new String[] {Directory.GetDemandDir(FullPath, true)};
-            new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false );
 #endif
             DisplayPath = GetDisplayName(OriginalPath, FullPath);
         }
@@ -169,7 +169,7 @@ namespace System.IO {
                 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery | FileSecurityStateAccess.Read, String.Empty, dir.demandDir[0]);
                 state.EnsureState();
 #else
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, dir.demandDir, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, dir.demandDir, false, false);
 #endif
                 return dir;
             }
@@ -234,7 +234,7 @@ namespace System.IO {
             FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, OriginalPath, demandDirForCreation);
             state.EnsureState();
 #else
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandDirForCreation }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, demandDirForCreation, false, false);
 #endif
 
             Directory.InternalCreateDirectory(fullPath, path, directorySecurity);
@@ -609,7 +609,7 @@ namespace System.IO {
                 FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath);
                 sourceState.EnsureState();
 #else
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPath, false, false);
 #endif
                 return new DirectoryInfo(rootPath);
             }
@@ -629,7 +629,7 @@ namespace System.IO {
             FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, DisplayPath, Directory.GetDemandDir(FullPath, true));
             sourceState.EnsureState();
 #else
-            new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandDir, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandDir, false, false);
 #endif
             String fullDestDirName = Path.GetFullPathInternal(destDirName);
             String demandPath;
@@ -648,9 +648,9 @@ namespace System.IO {
             FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destDirName, demandPath);
             destState.EnsureState();
 #else
-            new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandPath).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandPath);
 #endif
-            
+
             String fullSourcePath;
             if (FullPath.EndsWith(Path.DirectorySeparatorChar))
                 fullSourcePath = FullPath;
index d8a7146e01a3d267e204fdd6ba768ab31ebea7fd..8a36be7ee78a0cb577230549a239d4f1238eb177 100644 (file)
@@ -1322,10 +1322,23 @@ namespace System.IO {
             destState.EnsureState();
             backupState.EnsureState();
 #else
-            FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, new String[] { fullSrcPath, fullDestPath});
-            if (destinationBackupFileName != null)
-                perm.AddPathList(FileIOPermissionAccess.Write, fullBackupPath);
-            perm.Demand();
+#if FEATURE_CAS_POLICY
+            // All demands in full trust domains are no-ops, just do additional checks
+            if (CodeAccessSecurityEngine.QuickCheckForAllDemands())
+            {
+                FileIOPermission.EmulateFileIOPermissionChecks(fullSrcPath);
+                FileIOPermission.EmulateFileIOPermissionChecks(fullDestPath);
+                if (fullBackupPath != null)
+                    FileIOPermission.EmulateFileIOPermissionChecks(fullBackupPath);
+            }
+            else
+#endif
+            {
+                FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, new String[] { fullSrcPath, fullDestPath });
+                if (fullBackupPath != null)
+                    perm.AddPathList(FileIOPermissionAccess.Write, fullBackupPath);
+                perm.Demand();
+            }
 #endif
 
             int flags = Win32Native.REPLACEFILE_WRITE_THROUGH;
index f3da2cbd41494aebb6df942f558eec330533cadb..2402d9d2bdec1d287f5612c413bc2c3f101c9b46 100644 (file)
@@ -132,7 +132,7 @@ namespace System.IO {
         {
 #if FEATURE_MONO_CAS
 #if !FEATURE_CORECLR
-            new FileIOPermission(FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, FullPath, false, false);
 #endif
 #endif
             _name = Path.GetFileName(OriginalPath);
@@ -192,7 +192,7 @@ namespace System.IO {
                     FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, DisplayPath, FullPath);
                     state.EnsureState();
 #else
-                    new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { directoryName }, false, false).Demand();
+                    FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, directoryName, false, false);
 #endif
 #endif
                 }
@@ -344,7 +344,7 @@ namespace System.IO {
             state.EnsureState();
 #else
             // For security check, path should be resolved to an absolute path.
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { FullPath }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, FullPath, false, false);
 #endif
 #endif
 
@@ -483,7 +483,7 @@ namespace System.IO {
             sourceState.EnsureState();
             destState.EnsureState();
 #else
-            new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, FullPath, false, false);
             FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false);
 #endif
 #endif
index 38b86735241ea07f3ab33268fed4980d92d915dd..7e47b8bedeccb5022eb808e71cc10b40a7e730eb 100644 (file)
@@ -708,29 +708,26 @@ namespace System.IO {
             // Get absolute path - Security needs this to prevent something
             // like trying to create a file in c:\tmp with the name 
             // "..\WinNT\System32\ntoskrnl.exe".  Store it for user convenience.
-            int maxPath = useLongPath ? Path.MaxLongPath : Path.MaxPath;
-            String filePath = Path.NormalizePath(path, true, maxPath);
+            int maxPath = useLongPath
+                ? PathInternal.MaxLongPath 
+                : AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : PathInternal.MaxLongPath;
+
+            string filePath = Path.NormalizePath(path, true, maxPath);
 
             _fileName = filePath;
 
             // Prevent access to your disk drives as raw block devices.
-            if (filePath.StartsWith("\\\\.\\", StringComparison.Ordinal))
+            //
+            // We'll allow if in full trust and not in legacy mode. You can also get device access via \\?\ and \??\ so there isn't
+            // much point in making users jump through these hoops. Blocking is pointless in full trust as well.
+            if (
+#if FEATURE_CAS_POLICY
+                (!CodeAccessSecurityEngine.QuickCheckForAllDemands() || AppContextSwitches.UseLegacyPathHandling)
+                &&
+#endif
+                filePath.StartsWith("\\\\.\\", StringComparison.Ordinal))
                 throw new ArgumentException(Environment.GetResourceString("Arg_DevicesNotSupported"));
 
-            // In 4.0, we always construct a FileIOPermission object below. 
-            // If filePath contained a ':', we would throw a NotSupportedException in 
-            // System.Security.Util.StringExpressionSet.CanonicalizePath. 
-            // If filePath contained other illegal characters, we would throw an ArgumentException in 
-            // FileIOPermission.CheckIllegalCharacters.
-            // In 4.5 we on longer construct the FileIOPermission object in full trust.
-            // To preserve the 4.0 behavior we do an explicit check for ':' here and also call Path.CheckInvalidPathChars.
-            // Note that we need to call CheckInvalidPathChars before checking for ':' because that is what FileIOPermission does.
-
-            Path.CheckInvalidPathChars(filePath, true);
-
-            if (filePath.IndexOf( ':', 2 ) != -1)
-                throw new NotSupportedException( Environment.GetResourceString( "Argument_PathFormatNotSupported" ) );
-
             bool read = false;
 
 #if FEATURE_MACL
@@ -747,7 +744,12 @@ namespace System.IO {
 
             // All demands in full trust domains are no-ops, so skip 
 #if FEATURE_CAS_POLICY
-            if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) 
+            if (CodeAccessSecurityEngine.QuickCheckForAllDemands())
+            {
+                // Need to throw the same exceptions that are thrown if we actually called QuickDemand() below.
+                FileIOPermission.EmulateFileIOPermissionChecks(filePath);
+            }
+            else
 #endif // FEATURE_CAS_POLICY
             {
                 // Build up security permissions required, as well as validate we
@@ -796,7 +798,7 @@ namespace System.IO {
                 }
                 
                 AccessControlActions control = specifiedAcl ? AccessControlActions.Change : AccessControlActions.None;
-                new FileIOPermission(secAccess, control, new String[] { filePath }, false, false).Demand();
+                FileIOPermission.QuickDemand(secAccess, control, new String[] { filePath }, false, false);
 #else
 #if FEATURE_CORECLR
                 if (checkHost) {
@@ -804,7 +806,7 @@ namespace System.IO {
                     state.EnsureState();
                 }
 #else
-                new FileIOPermission(secAccess, new String[] { filePath }, false, false).Demand();
+                FileIOPermission.QuickDemand(secAccess, filePath, false, false);
 #endif // FEATURE_CORECLR
 #endif
             }
@@ -867,7 +869,7 @@ namespace System.IO {
                     {
                         try {
 #if !FEATURE_CORECLR
-                            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false ).Demand();
+                            FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, _fileName, false, false);
 #endif
                             canGiveFullPath = true;
                         }
@@ -1202,7 +1204,7 @@ namespace System.IO {
                 FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, _fileName);
                 sourceState.EnsureState();
 #else
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, _fileName, false, false);
 #endif
                 return _fileName;
             }
index ec69c33afb79d268bba6260634198d43464baa46..5acaf13e86d9a81336efeec78f3a130adb6d543f 100644 (file)
@@ -234,7 +234,7 @@ namespace System.IO
                     state2.EnsureState();
                 }
 #else
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false);
 #endif
 
                 // normalize search criteria
@@ -340,7 +340,7 @@ namespace System.IO
                     state2.EnsureState();
                 }
 #else
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false);
 #endif
                 searchData = new Directory.SearchData(normalizedSearchPath, userPath, searchOption);
                 CommonInit();
@@ -591,8 +591,7 @@ namespace System.IO
             }
 #else
             String demandDir = Directory.GetDemandDir(fullPathToDemand, true);
-            String[] demandPaths = new String[] { demandDir };
-            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandDir, false, false);
 #endif
         }
 
@@ -706,8 +705,7 @@ namespace System.IO
             FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name);
             state.EnsureState();
 #else
-            String[] names = new String[] { name };
-            new FileIOPermission(FileIOPermissionAccess.Read, names, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, name, false, false);
 #endif
             FileInfo fi = new FileInfo(name, false);
             fi.InitializeFrom(result.FindData);
@@ -733,8 +731,7 @@ namespace System.IO
             FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName);
             state.EnsureState();
 #else
-            String[] permissionNames = new String[] { permissionName };
-            new FileIOPermission(FileIOPermissionAccess.Read, permissionNames, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, permissionName, false, false);
 #endif
             DirectoryInfo di = new DirectoryInfo(name, false);
             di.InitializeFrom(result.FindData);
@@ -770,8 +767,7 @@ namespace System.IO
                 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName);
                 state.EnsureState();
 #else
-                String[] permissionNames = new String[] { permissionName };
-                new FileIOPermission(FileIOPermissionAccess.Read, permissionNames, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, permissionName, false, false);
 #endif
                 DirectoryInfo di = new DirectoryInfo(name, false);
                 di.InitializeFrom(result.FindData);
@@ -786,8 +782,7 @@ namespace System.IO
                 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name);
                 state.EnsureState();
 #else
-                String[] names = new String[] { name };
-                new FileIOPermission(FileIOPermissionAccess.Read, names, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, name, false, false);
 #endif
                 FileInfo fi = new FileInfo(name, false);
                 fi.InitializeFrom(result.FindData);
index c551e66159a62169796f281e8db3d27737838e1c..cf65efb2cf0e341e6f15f35d0b2f6dd804f88afd 100644 (file)
@@ -107,7 +107,7 @@ namespace System.IO {
                 FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandDir);
                 sourceState.EnsureState();
 #else
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandDir);
 #endif
 #endif
                 return FullPath;
@@ -126,7 +126,7 @@ namespace System.IO {
                     demandDir = FullPath;
 #if FEATURE_MONO_CAS
 #if !FEATURE_CORECLR
-                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandDir);
 #endif
 #endif
                 return FullPath;
@@ -353,7 +353,7 @@ namespace System.IO {
             set {
 #if FEATURE_MONO_CAS
 #if !FEATURE_CORECLR
-                new FileIOPermission(FileIOPermissionAccess.Write, FullPath).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, FullPath);
 #endif
 #endif
 #if MONO
@@ -386,7 +386,7 @@ namespace System.IO {
         {
 #if FEATURE_MONO_CAS
 #if !FEATURE_CORECLR
-            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, FullPath).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, FullPath);
 #endif
 #endif
 
index 2240ba9e1abb97fb7a6e1899c9c3aac2f76d3584..7b863b95c8dd326a302972e3d39f947d96bf37b4 100644 (file)
@@ -195,9 +195,9 @@ namespace System.IO {
             Contract.Requires(destFileName.Length > 0);
 
             String fullSourceFileName = LongPath.NormalizePath(sourceFileName);
-            new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullSourceFileName }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullSourceFileName, false, false);
             String fullDestFileName = LongPath.NormalizePath(destFileName);
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { fullDestFileName }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false);
 
             InternalCopy(fullSourceFileName, fullDestFileName, sourceFileName, destFileName, overwrite);
         }
@@ -258,7 +258,7 @@ namespace System.IO {
             String fullPath = LongPath.NormalizePath(path);
 
             // For security check, path should be resolved to an absolute path.
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { fullPath }, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullPath, false, false);
 
             String tempPath = Path.AddLongPathPrefix(fullPath);
             bool r = Win32Native.DeleteFile(tempPath);
@@ -297,8 +297,8 @@ namespace System.IO {
                 if (path.Length > 0 && Path.IsDirectorySeparator(path[path.Length - 1])) {
                     return false;
                 }
-                    
-                new FileIOPermission(FileIOPermissionAccess.Read, new String[] { path }, false, false ).Demand();
+
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, path, false, false );
 
                 return InternalExists(path);
             }
@@ -326,7 +326,7 @@ namespace System.IO {
             Contract.Requires(path != null);
 
             String fullPath = LongPath.NormalizePath(path);
-            new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
 
             String tempPath = Path.AddLongPathPrefix(fullPath);
 
@@ -348,7 +348,7 @@ namespace System.IO {
             Contract.Requires(path != null);
 
             String fullPath = LongPath.NormalizePath(path);
-            new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
 
             String tempPath = Path.AddLongPathPrefix(fullPath);
             Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
@@ -369,7 +369,7 @@ namespace System.IO {
             Contract.Requires(path != null);
 
             String fullPath = LongPath.NormalizePath(path);
-            new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
 
             String tempPath = Path.AddLongPathPrefix(fullPath);
             Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
@@ -400,9 +400,9 @@ namespace System.IO {
             Contract.Requires(destFileName.Length > 0);
 
             String fullSourceFileName = LongPath.NormalizePath(sourceFileName);
-            new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { fullSourceFileName }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, fullSourceFileName, false, false);
             String fullDestFileName = LongPath.NormalizePath(destFileName);
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { fullDestFileName }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false);
 
             if (!LongPathFile.InternalExists(fullSourceFileName))
                 __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, fullSourceFileName);
@@ -423,7 +423,7 @@ namespace System.IO {
             Contract.Requires(path != null);
 
             String fullPath = LongPath.NormalizePath(path);
-            new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
 
             String tempPath = Path.AddLongPathPrefix(fullPath);
             Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
@@ -435,7 +435,6 @@ namespace System.IO {
                 __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, path);
 
             return ((long)data.fileSizeHigh) << 32 | ((long)data.fileSizeLow & 0xFFFFFFFFL);
-            
         }
 
          // Defined in WinError.h
@@ -460,7 +459,7 @@ namespace System.IO {
             // We attempt to create directories only after all the security checks have passed. This is avoid doing
             // a demand at every level.
             String demandDir = GetDemandDir(fullPath, true);
-            new FileIOPermission(FileIOPermissionAccess.Read, new String[] { demandDir }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false);
 
             InternalCreateDirectory(fullPath, path, null);
         }
@@ -514,7 +513,15 @@ namespace System.IO {
 
             int count = stackDir.Count;
 
-            if (stackDir.Count != 0)
+            if (stackDir.Count != 0
+#if FEATURE_CAS_POLICY
+                // All demands in full trust domains are no-ops, so skip
+                //
+                // The full path went through validity checks by being passed through FileIOPermissions already.
+                // As a sub string of the full path can't fail the checks if the full path passes.
+                && !CodeAccessSecurityEngine.QuickCheckForAllDemands()
+#endif
+            )
             {
                 String[] securityList = new String[stackDir.Count];
                 stackDir.CopyTo(securityList, 0);
@@ -524,9 +531,9 @@ namespace System.IO {
                 // Security check for all directories not present only.
 #if !FEATURE_PAL  && FEATURE_MACL
                 AccessControlActions control = (dirSecurity == null) ? AccessControlActions.None : AccessControlActions.Change;
-                new FileIOPermission(FileIOPermissionAccess.Write, control, securityList, false, false ).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, control, securityList, false, false);
 #else
-                new FileIOPermission(FileIOPermissionAccess.Write, securityList, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, securityList, false, false);
 #endif
             }
 
@@ -554,9 +561,11 @@ namespace System.IO {
             {
                 String name = stackDir[stackDir.Count - 1];
                 stackDir.RemoveAt(stackDir.Count - 1);
+
                 if (name.Length >= Path.MaxLongPath)
                     throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
-                r = Win32Native.CreateDirectory(Path.AddLongPathPrefix(name), secAttrs);
+
+                r = Win32Native.CreateDirectory(PathInternal.EnsureExtendedPrefix(name), secAttrs);
                 if (!r && (firstError == 0))
                 {
                     int currentError = Marshal.GetLastWin32Error();
@@ -579,7 +588,7 @@ namespace System.IO {
                             // Give the user a nice error message, but don't leak path information.
                             try
                             {
-                                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { GetDemandDir(name, true) }, false, false).Demand();
+                                FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true), false, false);
                                 errorString = name;
                             }
                             catch (SecurityException) { }
@@ -631,8 +640,8 @@ namespace System.IO {
             if (destPath.Length >= Path.MaxLongPath)
                 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
 
-            new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { sourcePath }, false, false).Demand();
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { destPath }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, sourcePath, false, false);
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, destPath, false, false);
 
             if (String.Compare(sourcePath, destPath, StringComparison.OrdinalIgnoreCase) == 0)
                 throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustBeDifferent"));
@@ -643,8 +652,8 @@ namespace System.IO {
                 throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustHaveSameRoot"));
 
 
-            String tempSourceDirName = Path.AddLongPathPrefix(sourceDirName);
-            String tempDestDirName = Path.AddLongPathPrefix(destDirName);
+            String tempSourceDirName = PathInternal.EnsureExtendedPrefix(sourceDirName);
+            String tempDestDirName = PathInternal.EnsureExtendedPrefix(destDirName);
 
             if (!Win32Native.MoveFile(tempSourceDirName, tempDestDirName))
             {
@@ -683,7 +692,7 @@ namespace System.IO {
             demandPath = GetDemandDir(fullPath, !recursive);
 
             // Make sure we have write permission to this directory
-            new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandPath }, false, false).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, demandPath, false, false);
 
             String longPath = Path.AddLongPathPrefix(fullPath);
             // Do not recursively delete through reparse points.  Perhaps in a 
@@ -904,7 +913,7 @@ namespace System.IO {
                 String fullPath = LongPath.NormalizePath(path);
                 String demandPath = GetDemandDir(fullPath, true);
 
-                new FileIOPermission(FileIOPermissionAccess.Read, new String[] { demandPath }, false, false).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandPath, false, false);
 
                 return InternalExists(fullPath);
             }
index b4cb0ab7e360fe5d4493b767bfbb52be9ae1badb..3927d52da071c1f65fab9cde64c20dc95fcdf249 100644 (file)
@@ -55,19 +55,19 @@ namespace System.IO {
         // 
         public static readonly char DirectorySeparatorChar = '\\';
         internal const string DirectorySeparatorCharAsString = "\\";
-        
+
         // Platform specific alternate directory separator character.  
         // This is backslash ('\') on Unix, and slash ('/') on Windows 
         // and MacOS.
         // 
         public static readonly char AltDirectorySeparatorChar = '/';
-    
+
         // Platform specific volume separator character.  This is colon (':')
         // on Windows and MacOS, and slash ('/') on Unix.  This is mostly
-        // useful for parsing paths like "c:\windows" or "MacVolume:System Folder".  
+        // useful for parsing paths like "c:\windows" or "MacVolume:System Folder".
         // 
         public static readonly char VolumeSeparatorChar = ':';
-        
+
         // Platform specific invalid list of characters in a path.
         // See the "Naming a File" MSDN conceptual docs for more details on
         // what is valid in a file name (which is slightly different from what
@@ -77,10 +77,10 @@ namespace System.IO {
         public static readonly char[] InvalidPathChars = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31 };
 
         // Trim trailing white spaces, tabs etc but don't be aggressive in removing everything that has UnicodeCategory of trailing space.
-        // String.WhitespaceChars will trim aggressively than what the underlying FS does (for ex, NTFS, FAT).    
-        internal static readonly char[] TrimEndChars = { (char) 0x9, (char) 0xA, (char) 0xB, (char) 0xC, (char) 0xD, (char) 0x20,   (char) 0x85, (char) 0xA0};
-        
-        private static readonly char[] RealInvalidPathChars = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31 };
+        // String.WhitespaceChars will trim aggressively than what the underlying FS does (for ex, NTFS, FAT).
+        internal static readonly char[] TrimEndChars = LongPathHelper.s_trimEndChars;
+
+        private static readonly char[] RealInvalidPathChars = PathInternal.InvalidPathChars;
 
         // This is used by HasIllegalCharacters
         private static readonly char[] InvalidPathCharsWithAdditionalChecks = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31, '*', '?' };
@@ -89,16 +89,15 @@ namespace System.IO {
 
         public static readonly char PathSeparator = ';';
 
-
         // Make this public sometime.
         // The max total path is 260, and the max individual component length is 255. 
         // For example, D:\<256 char file name> isn't legal, even though it's under 260 chars.
-        internal static readonly int MaxPath = 260;
-        private static readonly int MaxDirectoryLength = 255;
+        internal static readonly int MaxPath = PathInternal.MaxShortPath;
+        private static readonly int MaxDirectoryLength = PathInternal.MaxComponentLength;
 
         // Windows API definitions
-        internal const int MAX_PATH = 260;  // From WinDef.h
-        internal const int MAX_DIRECTORY_PATH = 248;   // cannot create directories greater than 248 characters
+        internal const int MAX_PATH = PathInternal.MaxShortPath;  // From WinDef.h
+        internal const int MAX_DIRECTORY_PATH = PathInternal.MaxShortDirectoryPath;   // cannot create directories greater than 248 characters
     
         // Changes the extension of a file path. The path parameter
         // specifies a file path, and the extension parameter
@@ -136,7 +135,6 @@ namespace System.IO {
             return null;
         }
 
-       
         // Returns the directory path of a file path. This method effectively
         // removes the last element of the given file path, i.e. it returns a
         // string consisting of all characters up to but not including the last
@@ -146,7 +144,17 @@ namespace System.IO {
         //
         [ResourceExposure(ResourceScope.None)]
         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
-        public static String GetDirectoryName(String path) {
+        public static string GetDirectoryName(string path)
+        {
+            return InternalGetDirectoryName(path);
+        }
+
+        [ResourceExposure(ResourceScope.None)]
+        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
+        [System.Security.SecuritySafeCritical]
+
+        private static string InternalGetDirectoryName(string path)
+        {
             if (path != null) {
                 CheckInvalidPathChars(path);
 
@@ -154,16 +162,29 @@ namespace System.IO {
                 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
 #endif
 
-                string normalizedPath = NormalizePath(path, false);
+                // Expanding short paths is dangerous in this case as the results will change with the current directory.
+                //
+                // Suppose you have a path called "PICTUR~1\Foo". Now suppose you have two folders on disk "C:\Mine\Pictures Of Me"
+                // and "C:\Yours\Pictures of You". If the current directory is neither you'll get back "PICTUR~1". If it is "C:\Mine"
+                // get back "Pictures Of Me". "C:\Yours" would give back "Pictures of You".
+                //
+                // Because of this and as it isn't documented that short paths are expanded we will not expand short names unless
+                // we're in legacy mode.
+                string normalizedPath = NormalizePath(path, fullCheck: false, expandShortPaths: AppContextSwitches.UseLegacyPathHandling);
 
                 // If there are no permissions for PathDiscovery to this path, we should NOT expand the short paths
                 // as this would leak information about paths to which the user would not have access to.
-                if (path.Length > 0)
+                if (path.Length > 0
+#if FEATURE_CAS_POLICY
+                    // Only do the extra logic if we're not in full trust
+                    && !CodeAccessSecurityEngine.QuickCheckForAllDemands()
+#endif
+                    )
                 {
                     try
                     {
                         // If we were passed in a path with \\?\ we need to remove it as FileIOPermission does not like it.
-                        string tempPath = Path.RemoveLongPathPrefix(path);
+                        string tempPath = RemoveLongPathPrefix(path);
 
                         // FileIOPermission cannot handle paths that contain ? or *
                         // So we only pass to FileIOPermission the text up to them.
@@ -176,14 +197,14 @@ namespace System.IO {
                         // While we don't use the result of this call we are using it as a consistent way of 
                         // doing the security checks. 
                         if (pos > 0)
-                            Path.GetFullPath(tempPath.Substring(0, pos));
+                            GetFullPath(tempPath.Substring(0, pos));
                     }
                     catch (SecurityException) {
                         // If the user did not have permissions to the path, make sure that we don't leak expanded short paths
                         // Only re-normalize if the original path had a ~ in it.
                         if (path.IndexOf("~", StringComparison.Ordinal) != -1)
                         {
-                            normalizedPath = NormalizePath(path, /*fullCheck*/ false, /*expandShortPaths*/ false);
+                            normalizedPath = NormalizePath(path, fullCheck: false, expandShortPaths: false);
                         }
                     }
                     catch (PathTooLongException) { }
@@ -203,13 +224,13 @@ namespace System.IO {
                 if (i > root) {
                     i = path.Length;
                     if (i == root) return null;
-                    while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar);                    
+                    while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar);
                     String dir = path.Substring(0, i);
 #if FEATURE_LEGACYNETCF
-                    if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {                        
+                    if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
                         if (dir.Length >= MAX_PATH - 1)
                             throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
-                    }                     
+                    }
 #endif
                     return dir;
                 }
@@ -220,9 +241,22 @@ namespace System.IO {
         // Gets the length of the root DirectoryInfo or whatever DirectoryInfo markers
         // are specified for the first part of the DirectoryInfo name.
         // 
-        internal static int GetRootLength(String path) {
+        internal static int GetRootLength(string path)
+        {
             CheckInvalidPathChars(path);
-            
+
+            if (AppContextSwitches.UseLegacyPathHandling)
+            {
+                return LegacyGetRootLength(path);
+            }
+            else
+            {
+                return PathInternal.GetRootLength(path);
+            }
+        }
+
+        private static int LegacyGetRootLength(string path)
+        {
             int i = 0;
             int length = path.Length;
 
@@ -247,7 +281,6 @@ namespace System.IO {
             return (c==DirectorySeparatorChar || c == AltDirectorySeparatorChar);
         }
 
-
         public static char[] GetInvalidPathChars()
         {
             return (char[]) RealInvalidPathChars.Clone();
@@ -330,7 +363,7 @@ namespace System.IO {
                 throw new ArgumentNullException("path");
             Contract.EndContractBlock();
 
-            String newPath = NormalizePath(path, true);
+            string newPath = NormalizePath(path, fullCheck: true);
 
             return newPath;
         }
@@ -338,8 +371,9 @@ namespace System.IO {
         [System.Security.SecuritySafeCritical]  // auto-generated
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        internal unsafe static String NormalizePath(String path, bool fullCheck) {
-            return NormalizePath(path, fullCheck, MaxPath);
+        internal unsafe static String NormalizePath(String path, bool fullCheck)
+        {
+            return NormalizePath(path, fullCheck, AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : PathInternal.MaxLongPath);
         }
 
         [System.Security.SecuritySafeCritical]  // auto-generated
@@ -347,31 +381,127 @@ namespace System.IO {
         [ResourceConsumption(ResourceScope.Machine)]
         internal unsafe static String NormalizePath(String path, bool fullCheck, bool expandShortPaths)
         {
-            return NormalizePath(path, fullCheck, MaxPath, expandShortPaths);
+            return NormalizePath(path, fullCheck, MaxPath, expandShortPaths: expandShortPaths);
         }
 
         [System.Security.SecuritySafeCritical]  // auto-generated
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
         internal unsafe static String NormalizePath(String path, bool fullCheck, int maxPathLength) {
-            return NormalizePath(path, fullCheck, maxPathLength, true);
+            return NormalizePath(path, fullCheck, maxPathLength, expandShortPaths: true);
         }
 
-        [System.Security.SecurityCritical]  // auto-generated
+        [System.Security.SecuritySafeCritical]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        internal unsafe static String NormalizePath(String path, bool fullCheck, int maxPathLength, bool expandShortPaths) {
+        internal static string NormalizePath(string path, bool fullCheck, int maxPathLength, bool expandShortPaths)
+        {
+            if (AppContextSwitches.UseLegacyPathHandling)
+            {
+                return LegacyNormalizePath(path, fullCheck, maxPathLength, expandShortPaths);
+            }
+            else
+            {
+                if (PathInternal.IsExtended(path))
+                {
+                    // We can't really know what is valid for all cases of extended paths.
+                    //
+                    //  - object names can include other characters as well (':', '/', etc.)
+                    //  - even file objects have different rules (pipe names can contain most characters)
+                    //
+                    // As such we will do no further analysis of extended paths to avoid blocking known and unknown
+                    // scenarios as well as minimizing compat breaks should we block now and need to unblock later.
+                    return path;
+                }
+
+                string normalizedPath = null;
 
+                if (fullCheck == false)
+                {
+                    // Disabled fullCheck is only called by GetDirectoryName and GetPathRoot.
+                    // Avoid adding addtional callers and try going direct to lighter weight NormalizeDirectorySeparators.
+                    normalizedPath = NewNormalizePathLimitedChecks(path, maxPathLength, expandShortPaths);
+                }
+                else
+                {
+                    normalizedPath = NewNormalizePath(path, maxPathLength, expandShortPaths: true);
+                }
+
+                if (string.IsNullOrWhiteSpace(normalizedPath))
+                    throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+                return normalizedPath;
+            }
+        }
+
+        [System.Security.SecuritySafeCritical]
+        private static string NewNormalizePathLimitedChecks(string path, int maxPathLength, bool expandShortPaths)
+        {
+            string normalized = PathInternal.NormalizeDirectorySeparators(path);
+
+            if (PathInternal.IsPathTooLong(normalized) || PathInternal.AreSegmentsTooLong(normalized))
+                throw new PathTooLongException();
+
+            if (!PathInternal.IsDevice(normalized) && PathInternal.HasInvalidVolumeSeparator(path))
+                throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+            if (expandShortPaths && normalized.IndexOf('~') != -1)
+            {
+                try
+                {
+                    return LongPathHelper.GetLongPathName(normalized);
+                }
+                catch
+                {
+                    // Don't care if we can't get the long path- might not exist, etc.
+                }
+            }
+
+            return normalized;
+        }
+
+        /// <summary>
+        /// Normalize the path and check for bad characters or other invalid syntax.
+        /// </summary>
+        [System.Security.SecuritySafeCritical]
+        [ResourceExposure(ResourceScope.Machine)]
+        [ResourceConsumption(ResourceScope.Machine)]
+        private static string NewNormalizePath(string path, int maxPathLength, bool expandShortPaths)
+        {
             Contract.Requires(path != null, "path can't be null");
-            // If we're doing a full path check, trim whitespace and look for
-            // illegal path characters.
-            if (fullCheck) {
+
+            // Embedded null characters are the only invalid character case we want to check up front.
+            // This is because the nulls will signal the end of the string to Win32 and therefore have
+            // unpredictable results. Other invalid characters we give a chance to be normalized out.
+            if (path.IndexOf('\0') != -1)
+                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
+
+            // Note that colon and wildcard checks happen in FileIOPermissions
+
+            // Technically this doesn't matter but we used to throw for this case
+            if (string.IsNullOrWhiteSpace(path))
+                throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+            // We don't want to check invalid characters for device format- see comments for extended above
+            return LongPathHelper.Normalize(path, (uint)maxPathLength, checkInvalidCharacters: !PathInternal.IsDevice(path), expandShortPaths: expandShortPaths);
+        }
+
+        [System.Security.SecurityCritical]  // auto-generated
+        [ResourceExposure(ResourceScope.Machine)]
+        [ResourceConsumption(ResourceScope.Machine)]
+        internal unsafe static string LegacyNormalizePath(string path, bool fullCheck, int maxPathLength, bool expandShortPaths)
+        {
+            Contract.Requires(path != null, "path can't be null");
+            
+            // If we're doing a full path check, trim whitespace and look for illegal path characters.
+            if (fullCheck)
+            {
                 // Trim whitespace off the end of the string.
                 // Win32 normalization trims only U+0020. 
                 path = path.TrimEnd(TrimEndChars);
 
                 // Look for illegal path characters.
-                CheckInvalidPathChars(path);
+                if (PathInternal.AnyPathHasIllegalCharacters(path))
+                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
             }
 
             int index = 0;
@@ -777,50 +907,75 @@ namespace System.IO {
             return returnVal;
 
         }
-        internal const int MaxLongPath = 32000;
 
-        private const string LongPathPrefix = @"\\?\";
-        private const string UNCPathPrefix = @"\\";
-        private const string UNCLongPathPrefixToInsert = @"?\UNC\";
-        private const string UNCLongPathPrefix = @"\\?\UNC\";
+        internal const int MaxLongPath = PathInternal.MaxLongPath;
 
-        internal unsafe static bool HasLongPathPrefix(String path)
+        private const string LongPathPrefix = PathInternal.ExtendedPathPrefix;
+        private const string UNCPathPrefix = PathInternal.UncPathPrefix;
+        private const string UNCLongPathPrefixToInsert = PathInternal.UncExtendedPrefixToInsert;
+        private const string UNCLongPathPrefix = PathInternal.UncExtendedPathPrefix;
+
+        internal static bool HasLongPathPrefix(string path)
         {
-            return path.StartsWith(LongPathPrefix, StringComparison.Ordinal);
+            if (AppContextSwitches.UseLegacyPathHandling)
+                return path.StartsWith(LongPathPrefix, StringComparison.Ordinal);
+            else
+                return PathInternal.IsExtended(path);
         }
 
-        internal unsafe static String AddLongPathPrefix(String path)
+        internal static string AddLongPathPrefix(string path)
         {
-            if (path.StartsWith(LongPathPrefix, StringComparison.Ordinal))
-                return path;
+            if (AppContextSwitches.UseLegacyPathHandling)
+            {
+                if (path.StartsWith(LongPathPrefix, StringComparison.Ordinal))
+                    return path;
 
-            if (path.StartsWith(UNCPathPrefix, StringComparison.Ordinal))
-                return path.Insert(2, UNCLongPathPrefixToInsert); // Given \\server\share in longpath becomes \\?\UNC\server\share  => UNCLongPathPrefix + path.SubString(2); => The actual command simply reduces the operation cost.
+                if (path.StartsWith(UNCPathPrefix, StringComparison.Ordinal))
+                    return path.Insert(2, UNCLongPathPrefixToInsert); // Given \\server\share in longpath becomes \\?\UNC\server\share  => UNCLongPathPrefix + path.SubString(2); => The actual command simply reduces the operation cost.
 
-            return LongPathPrefix + path;
+                return LongPathPrefix + path;
+            }
+            else
+            {
+                return PathInternal.EnsureExtendedPrefix(path);
+            }
         }
 
-        internal unsafe static String RemoveLongPathPrefix(String path)
+        internal static string RemoveLongPathPrefix(string path)
         {
-            if (!path.StartsWith(LongPathPrefix, StringComparison.Ordinal))
-                return path;
+            if (AppContextSwitches.UseLegacyPathHandling)
+            {
+                if (!path.StartsWith(LongPathPrefix, StringComparison.Ordinal))
+                    return path;
 
-            if (path.StartsWith(UNCLongPathPrefix, StringComparison.OrdinalIgnoreCase))
-                return path.Remove(2, 6); // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost.
+                if (path.StartsWith(UNCLongPathPrefix, StringComparison.OrdinalIgnoreCase))
+                    return path.Remove(2, 6); // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost.
 
-            return path.Substring(4);
+                return path.Substring(4);
+            }
+            else
+            {
+                return PathInternal.RemoveExtendedPrefix(path);
+            }
         }
 
-        internal unsafe static StringBuilder RemoveLongPathPrefix(StringBuilder pathSB)
+        internal static StringBuilder RemoveLongPathPrefix(StringBuilder pathSB)
         {
-            string path = pathSB.ToString();
-            if (!path.StartsWith(LongPathPrefix, StringComparison.Ordinal))
-                return pathSB;
+            if (AppContextSwitches.UseLegacyPathHandling)
+            {
+                if (!PathInternal.StartsWithOrdinal(pathSB, LongPathPrefix))
+                    return pathSB;
 
-            if (path.StartsWith(UNCLongPathPrefix, StringComparison.OrdinalIgnoreCase))
-                return pathSB.Remove(2, 6);  // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost.
+                // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost.
+                if (PathInternal.StartsWithOrdinal(pathSB, UNCLongPathPrefix, ignoreCase: true))
+                    return pathSB.Remove(2, 6);
 
-            return pathSB.Remove(0, 4);
+                return pathSB.Remove(0, 4);
+            }
+            else
+            {
+                return PathInternal.RemoveExtendedPrefix(pathSB);
+            }
         }
 
         // Returns the name and extension parts of the given path. The resulting
@@ -860,8 +1015,6 @@ namespace System.IO {
             return null;
          }
 
-
-
         // Returns the root portion of the given path. The resulting string
         // consists of those rightmost characters of the path that constitute the
         // root of the path. Possible patterns for the resulting string are: An
@@ -876,7 +1029,10 @@ namespace System.IO {
         [ResourceConsumption(ResourceScope.Machine)]
         public static String GetPathRoot(String path) {
             if (path == null) return null;
-            path = NormalizePath(path, false);
+
+            // Expanding short paths has no impact on the path root- there is no such thing as an
+            // 8.3 volume or server/share name.
+            path = NormalizePath(path, fullCheck: false, expandShortPaths: false);
             return path.Substring(0, GetRootLength(path));
         }
 
@@ -903,15 +1059,9 @@ namespace System.IO {
         internal static bool IsRelative(string path)
         {
             Contract.Assert(path != null, "path can't be null");
-            if ((path.Length >= 3 && path[1] == VolumeSeparatorChar && path[2] == DirectorySeparatorChar && 
-                   ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'))) ||
-                  (path.Length >= 2 && path[0] == '\\' && path[1] == '\\'))
-                return false;
-            else
-                return true;
-        
+            return PathInternal.IsPartiallyQualified(path);
         }
-                
+
         // Returns a cryptographically strong random 8.3 string that can be 
         // used as either a folder name or a file name.
         public static String GetRandomFileName()
@@ -978,7 +1128,7 @@ namespace System.IO {
                 state.EnsureState();
             }
 #else
-            new FileIOPermission(FileIOPermissionAccess.Write, path).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, path);
 #endif
             StringBuilder sb = new StringBuilder(MAX_PATH);
             uint r = Win32Native.GetTempFileName(path, "tmp", 0, sb);
@@ -1214,31 +1364,17 @@ namespace System.IO {
                 
                 searchPattern = searchPattern.Substring(index + 2);
             }
-
-        }
-
-        internal static bool HasIllegalCharacters(String path, bool checkAdditional)
-        {
-            Contract.Requires(path != null);
-
-            if (checkAdditional)
-            {
-                return path.IndexOfAny(InvalidPathCharsWithAdditionalChecks) >= 0;
-            }
-
-            return path.IndexOfAny(RealInvalidPathChars) >= 0;
         }
 
-        internal static void CheckInvalidPathChars(String path, bool checkAdditional = false)
+        internal static void CheckInvalidPathChars(string path, bool checkAdditional = false)
         {
             if (path == null)
                 throw new ArgumentNullException("path");
 
-            if (Path.HasIllegalCharacters(path, checkAdditional))
+            if (PathInternal.HasIllegalCharacters(path, checkAdditional))
                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
         }
 
-        
         internal static String InternalCombine(String path1, String path2) {
             if (path1==null || path2==null)
                 throw new ArgumentNullException((path1==null) ? "path1" : "path2");
index a67ee8c29f5e2dd88e2b7b61e8f8b225225ec2be..33c341eb4f74e4712112b521515ed6b665e192f2 100644 (file)
@@ -1014,10 +1014,15 @@ namespace System.Resources {
                 }
             }
             else {
-                int seekPos = unchecked(4 * _numResources);
-                if (seekPos < 0) {
+                // The hexadecimal E translates to binary 1110
+                // So, with this & condition we are checking that none of the highest 3 bits are
+                // set before multiplying, as that would cause an overflow.
+                if ((_numResources & 0xE0000000) != 0){
+
                     throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
                 }
+
+                int seekPos = unchecked(4 * _numResources);
                 unsafe {
                     _nameHashesPtr = (int*)_ums.PositionPointer;
                     // Skip over the array of nameHashes.
@@ -1046,10 +1051,14 @@ namespace System.Resources {
                 }
             }
             else {
-                int seekPos = unchecked(4 * _numResources);
-                if (seekPos < 0) {
+                // The hexadecimal E translates to binary 1110
+                // So, with this & condition we are checking that none of the highest 3 bits are
+                // set before multiplying, as that would cause an overflow.
+                if ((_numResources & 0xE0000000) != 0){
                     throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
                 }
+
+                int seekPos = unchecked(4 * _numResources);
                 unsafe {
                     _namePositionsPtr = (int*)_ums.PositionPointer;
                     // Skip over the array of namePositions.
index f9cec78699ee1800fbf558199af55615f06136d1..893340d673cce042baf7095737d8323f3ec456a1 100644 (file)
@@ -28,22 +28,26 @@ namespace System.Runtime.InteropServices.WindowsRuntime
         [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll", PreserveSig = false)]
         [SecurityCritical]
         [SuppressUnmanagedCodeSecurity]
+        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
         internal static extern IRestrictedErrorInfo GetRestrictedErrorInfo();
 
         [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll")]
         [SecurityCritical]
         [SuppressUnmanagedCodeSecurity]
         [return: MarshalAs(UnmanagedType.Bool)]
+        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
         internal static extern bool RoOriginateLanguageException(int error, [MarshalAs(UnmanagedType.HString)]string message, IntPtr languageException);
 
         [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll", PreserveSig = false)]
         [SecurityCritical]
         [SuppressUnmanagedCodeSecurity]
+        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
         internal static extern void RoReportUnhandledError(IRestrictedErrorInfo error);
 
         [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
         [SecurityCritical]
         [SuppressUnmanagedCodeSecurity]
+        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
         internal static unsafe extern int WindowsCreateString([MarshalAs(UnmanagedType.LPWStr)] string sourceString,
                                                               int length,
                                                               [Out] IntPtr *hstring);
@@ -51,6 +55,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
         [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
         [SecurityCritical]
         [SuppressUnmanagedCodeSecurity]
+        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
         internal static unsafe extern int WindowsCreateStringReference(char *sourceString,
                                                                        int length,
                                                                        [Out] HSTRING_HEADER *hstringHeader,
@@ -59,11 +64,13 @@ namespace System.Runtime.InteropServices.WindowsRuntime
         [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
         [SecurityCritical]
         [SuppressUnmanagedCodeSecurity]
+        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
         internal static extern int WindowsDeleteString(IntPtr hstring);
 
         [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
         [SecurityCritical]
         [SuppressUnmanagedCodeSecurity]
+        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
         internal static unsafe extern char* WindowsGetStringRawBuffer(IntPtr hstring, [Out] uint *length);
     }
 }
index 59c44820f332c5766b872a09496333ae9f3b849f..fad7beb385e27907e78615202a7e9fa5787deb6b 100644 (file)
@@ -435,9 +435,9 @@ namespace System.Security.AccessControl
         [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        internal void Persist( String fullPath )
+        internal void Persist(string fullPath)
         {
-            new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand();
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath);
 
             WriteLock();
 
@@ -455,12 +455,12 @@ namespace System.Security.AccessControl
         
         [System.Security.SecuritySafeCritical]  // auto-generated
         [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
-        internal void Persist( SafeFileHandle handle, String fullPath )
+        internal void Persist(SafeFileHandle handle, string fullPath)
         {
-            if ( fullPath != null )
-                new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand();
+            if (fullPath != null)
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath);
             else
-                new FileIOPermission( PermissionState.Unrestricted ).Demand();
+                FileIOPermission.QuickDemand(PermissionState.Unrestricted);
 
             WriteLock();
 
@@ -627,11 +627,9 @@ namespace System.Security.AccessControl
 
     public sealed class FileSecurity : FileSystemSecurity
     {
-        #region Constructors
-
         [System.Security.SecuritySafeCritical]  // auto-generated
         public FileSecurity()
-            : base( false )
+            : base(false)
         {
         }
 
@@ -639,11 +637,11 @@ namespace System.Security.AccessControl
         [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        public FileSecurity( String fileName, AccessControlSections includeSections )
+        public FileSecurity(string fileName, AccessControlSections includeSections)
             : base(false, fileName, includeSections, false)
         {
-            String fullPath = Path.GetFullPathInternal(fileName);
-            new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand();
+            string fullPath = Path.GetFullPathInternal(fileName);
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath, checkForDuplicates: false, needFullPath: false);
         }
 
         // Warning!  Be exceedingly careful with this constructor.  Do not make
@@ -654,26 +652,21 @@ namespace System.Security.AccessControl
         [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        internal FileSecurity( SafeFileHandle handle, String fullPath, AccessControlSections includeSections )
-            : base( false, handle, includeSections, false )
+        internal FileSecurity(SafeFileHandle handle, string fullPath, AccessControlSections includeSections)
+            : base(false, handle, includeSections, false)
         {
             if (fullPath != null)
-                new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand();
+                FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath);
             else
-                new FileIOPermission(PermissionState.Unrestricted).Demand();
+                FileIOPermission.QuickDemand(PermissionState.Unrestricted);
         }
-
-        #endregion
     }
-    
 
     public sealed class DirectorySecurity : FileSystemSecurity
     {
-        #region Constructors
-
         [System.Security.SecuritySafeCritical]  // auto-generated
         public DirectorySecurity()
-            : base( true )
+            : base(true)
         {
         }
 
@@ -681,14 +674,12 @@ namespace System.Security.AccessControl
         [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        public DirectorySecurity( String name, AccessControlSections includeSections )
-            : base( true, name, includeSections, true )
+        public DirectorySecurity(string name, AccessControlSections includeSections)
+            : base(true, name, includeSections, true)
         {
-            String fullPath = Path.GetFullPathInternal(name);
-            new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand();
+            string fullPath = Path.GetFullPathInternal(name);
+            FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath, checkForDuplicates: false, needFullPath: false);
         }
-
-        #endregion
     }
 }
 
index 5b8627cd9b0c8034c73aa5837cc632fbf5c59d3e..5f3a25e79b72ee61df57ce06bf256a9e1dfc6ccb 100644 (file)
@@ -315,7 +315,14 @@ namespace System.Security.Claims
                     //
                     if(!IsCircular(claimsIdentity.Actor))
                     {
-                        m_actor = claimsIdentity.Actor;
+                        if (!AppContextSwitches.SetActorAsReferenceWhenCopyingClaimsIdentity)
+                        {
+                            m_actor = claimsIdentity.Actor.Clone();
+                        }
+                        else
+                        {
+                            m_actor = claimsIdentity.Actor;
+                        }
                     }
                     else
                     {
@@ -334,6 +341,10 @@ namespace System.Security.Claims
                 else
                     SafeAddClaims(claimsIdentity.m_instanceClaims);
 
+                if (claimsIdentity.m_userSerializationData != null)
+                {
+                    m_userSerializationData = claimsIdentity.m_userSerializationData.Clone() as byte[];
+                }
             }
             else
             {
@@ -594,7 +605,14 @@ namespace System.Security.Claims
                 // the Actor property and so not really needed here. But checking just for sanity sake
                 if(!IsCircular(this.Actor))
                 {
-                    newIdentity.Actor = this.Actor;
+                    if (!AppContextSwitches.SetActorAsReferenceWhenCopyingClaimsIdentity)
+                    {
+                        newIdentity.Actor = this.Actor.Clone();
+                    }
+                    else
+                    {
+                        newIdentity.Actor = this.Actor;
+                    }
                 }
                 else
                 {
@@ -945,6 +963,7 @@ namespace System.Security.Claims
                 return;
 
             m_instanceClaims = new List<Claim>();
+
             m_externalClaims = new Collection<IEnumerable<Claim>>();
         }
 
index 7d3eb777e4283de76e435faeed2d22a95148c58e..667369d2dd6c338e9f5d0c52a4fdc3b4eee79a62 100644 (file)
@@ -122,6 +122,7 @@ namespace System.Security.Cryptography {
 #endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
 #if FEATURE_CRYPTO
                     ht.Add("System.Security.Cryptography.SHA1CryptoServiceProvider", Constants.OID_OIWSEC_SHA1);
+                    ht.Add("System.Security.Cryptography.SHA1Cng", Constants.OID_OIWSEC_SHA1);
 #endif //FEATURE_CRYPTO
 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
                     ht.Add("System.Security.Cryptography.SHA1Managed", Constants.OID_OIWSEC_SHA1);
@@ -174,13 +175,6 @@ namespace System.Security.Cryptography {
 #if FEATURE_CRYPTO
                     Type SHA1CryptoServiceProviderType = typeof(System.Security.Cryptography.SHA1CryptoServiceProvider);
                     Type MD5CryptoServiceProviderType = typeof(System.Security.Cryptography.MD5CryptoServiceProvider);
-#endif //FEATURE_CRYPTO
-#if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
-                    Type SHA256ManagedType = typeof(SHA256Managed);
-#endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
-#if FEATURE_CRYPTO
-                    Type SHA384ManagedType = typeof(SHA384Managed);
-                    Type SHA512ManagedType = typeof(SHA512Managed);
                     Type RIPEMD160ManagedType  = typeof(System.Security.Cryptography.RIPEMD160Managed); 
                     Type HMACMD5Type       = typeof(System.Security.Cryptography.HMACMD5);
                     Type HMACRIPEMD160Type = typeof(System.Security.Cryptography.HMACRIPEMD160);
@@ -209,6 +203,9 @@ namespace System.Security.Cryptography {
 #if FEATURE_CRYPTO
                     Type DSASignatureDescriptionType = typeof(System.Security.Cryptography.DSASignatureDescription);
                     Type RSAPKCS1SHA1SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA1SignatureDescription);
+                    Type RSAPKCS1SHA256SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA256SignatureDescription);
+                    Type RSAPKCS1SHA384SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA384SignatureDescription);
+                    Type RSAPKCS1SHA512SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA512SignatureDescription);
 #endif //FEATURE_CRYPTO
 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
                     Type RNGCryptoServiceProviderType = typeof(System.Security.Cryptography.RNGCryptoServiceProvider);
@@ -233,11 +230,26 @@ namespace System.Security.Cryptography {
                     string SHA384CryptoSerivceProviderType = "System.Security.Cryptography.SHA384CryptoServiceProvider, " + AssemblyRef.SystemCore;
                     string SHA512CngType = "System.Security.Cryptography.SHA512Cng, " + AssemblyRef.SystemCore;
                     string SHA512CryptoServiceProviderType = "System.Security.Cryptography.SHA512CryptoServiceProvider, " + AssemblyRef.SystemCore;
+#endif //FEATURE_CRYPTO
+
+
+#if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
+                    bool fipsOnly = AllowOnlyFipsAlgorithms;
+                    object SHA256DefaultType = typeof(SHA256Managed);
+#endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
+
+#if FEATURE_CRYPTO
+                    if (fipsOnly)
+                    {
+                        SHA256DefaultType = SHA256CngType;
+                    }
+                    object SHA384DefaultType = fipsOnly ? (object)SHA384CngType : (object)typeof(SHA384Managed);
+                    object SHA512DefaultType = fipsOnly ? (object)SHA512CngType : (object)typeof(SHA512Managed);
 
                     // Cryptography algorithms in System.Security
                     string DpapiDataProtectorType = "System.Security.Cryptography.DpapiDataProtector, " + AssemblyRef.SystemSecurity;
-
 #endif //FEATURE_CRYPTO
+
 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
                     // Random number generator
                     ht.Add("RandomNumberGenerator", RNGCryptoServiceProviderType);
@@ -256,21 +268,21 @@ namespace System.Security.Cryptography {
                     ht.Add("System.Security.Cryptography.MD5Cng", MD5CngType);
 #endif //FEATURE_CRYPTO
 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
-                    ht.Add("SHA256", SHA256ManagedType);
-                    ht.Add("SHA-256", SHA256ManagedType);
-                    ht.Add("System.Security.Cryptography.SHA256", SHA256ManagedType);
+                    ht.Add("SHA256", SHA256DefaultType);
+                    ht.Add("SHA-256", SHA256DefaultType);
+                    ht.Add("System.Security.Cryptography.SHA256", SHA256DefaultType);
 #endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
 #if FEATURE_CRYPTO
                     ht.Add("System.Security.Cryptography.SHA256Cng", SHA256CngType);
                     ht.Add("System.Security.Cryptography.SHA256CryptoServiceProvider", SHA256CryptoServiceProviderType);
-                    ht.Add("SHA384", SHA384ManagedType);
-                    ht.Add("SHA-384", SHA384ManagedType);
-                    ht.Add("System.Security.Cryptography.SHA384", SHA384ManagedType);
+                    ht.Add("SHA384", SHA384DefaultType);
+                    ht.Add("SHA-384", SHA384DefaultType);
+                    ht.Add("System.Security.Cryptography.SHA384", SHA384DefaultType);
                     ht.Add("System.Security.Cryptography.SHA384Cng", SHA384CngType);
                     ht.Add("System.Security.Cryptography.SHA384CryptoServiceProvider", SHA384CryptoSerivceProviderType);
-                    ht.Add("SHA512", SHA512ManagedType);
-                    ht.Add("SHA-512", SHA512ManagedType);
-                    ht.Add("System.Security.Cryptography.SHA512", SHA512ManagedType);
+                    ht.Add("SHA512", SHA512DefaultType);
+                    ht.Add("SHA-512", SHA512DefaultType);
+                    ht.Add("System.Security.Cryptography.SHA512", SHA512DefaultType);
                     ht.Add("System.Security.Cryptography.SHA512Cng", SHA512CngType);
                     ht.Add("System.Security.Cryptography.SHA512CryptoServiceProvider", SHA512CryptoServiceProviderType);
                     ht.Add("RIPEMD160", RIPEMD160ManagedType);
@@ -357,16 +369,19 @@ namespace System.Security.Cryptography {
                     ht.Add("System.Security.Cryptography.DSASignatureDescription", DSASignatureDescriptionType);
                     ht.Add("http://www.w3.org/2000/09/xmldsig#rsa-sha1", RSAPKCS1SHA1SignatureDescriptionType);
                     ht.Add("System.Security.Cryptography.RSASignatureDescription", RSAPKCS1SHA1SignatureDescriptionType);
+                    ht.Add("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", RSAPKCS1SHA256SignatureDescriptionType);
+                    ht.Add("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", RSAPKCS1SHA384SignatureDescriptionType);
+                    ht.Add("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", RSAPKCS1SHA512SignatureDescriptionType);
 
                     // Xml Dsig/Enc Hash algorithms
                     ht.Add("http://www.w3.org/2000/09/xmldsig#sha1", SHA1CryptoServiceProviderType);
                     // Add the other hash algorithms introduced with XML Encryption
 #endif //FEATURE_CRYPTO
 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
-                    ht.Add("http://www.w3.org/2001/04/xmlenc#sha256", SHA256ManagedType);
+                    ht.Add("http://www.w3.org/2001/04/xmlenc#sha256", SHA256DefaultType);
 #endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
 #if FEATURE_CRYPTO && !FEATURE_CORECLR
-                    ht.Add("http://www.w3.org/2001/04/xmlenc#sha512", SHA512ManagedType);
+                    ht.Add("http://www.w3.org/2001/04/xmlenc#sha512", SHA512DefaultType);
                     ht.Add("http://www.w3.org/2001/04/xmlenc#ripemd160", RIPEMD160ManagedType);
 
                     // Xml Encryption symmetric keys
@@ -421,7 +436,7 @@ namespace System.Security.Cryptography {
 
                     // Xml Dsig-more Uri's as defined in http://www.ietf.org/rfc/rfc4051.txt
                     ht.Add("http://www.w3.org/2001/04/xmldsig-more#md5", MD5CryptoServiceProviderType);
-                    ht.Add("http://www.w3.org/2001/04/xmldsig-more#sha384", SHA384ManagedType);
+                    ht.Add("http://www.w3.org/2001/04/xmldsig-more#sha384", SHA384DefaultType);
                     ht.Add("http://www.w3.org/2001/04/xmldsig-more#hmac-md5", HMACMD5Type);
                     ht.Add("http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160", HMACRIPEMD160Type);
 #endif //FEATURE_CRYPTO
index 51f9a9ae4cc12961e7f4424fab286906191e63b6..af2db6e53039c4ce911fdba24cc8d5933292a85d 100644 (file)
@@ -15,6 +15,7 @@ namespace System.Security.Cryptography {
     using System.Runtime.Serialization;
     using System.Security.Util;
     using System.Globalization;
+    using System.IO;
     using System.Diagnostics.Contracts;
 
     // DSAParameters is serializable so that one could pass the public parameters
@@ -63,10 +64,78 @@ namespace System.Security.Cryptography {
             return (DSA) CryptoConfig.CreateFromName(algName);
         }
 
+        // DSA does not encode the algorithm identifier into the signature blob, therefore CreateSignature and
+        // VerifySignature do not need the HashAlgorithmName value, only SignData and VerifyData do.
         abstract public byte[] CreateSignature(byte[] rgbHash);
 
         abstract public bool VerifySignature(byte[] rgbHash, byte[] rgbSignature); 
 
+        protected virtual byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
+        {
+            throw DerivedClassMustOverride();
+        }
+
+        protected virtual byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm)
+        {
+            throw DerivedClassMustOverride();
+        }
+
+        public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm)
+        {
+            if (data == null) { throw new ArgumentNullException("data"); }
+
+            return SignData(data, 0, data.Length, hashAlgorithm);
+        }
+
+        public virtual byte[] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
+        {
+            if (data == null) { throw new ArgumentNullException("data"); }
+            if (offset < 0 || offset > data.Length) { throw new ArgumentOutOfRangeException("offset"); }
+            if (count < 0 || count > data.Length - offset) { throw new ArgumentOutOfRangeException("count"); }
+            if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); }
+
+            byte[] hash = HashData(data, offset, count, hashAlgorithm);
+            return CreateSignature(hash);
+        }
+
+        public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm)
+        {
+            if (data == null) { throw new ArgumentNullException("data"); }
+            if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); }
+
+            byte[] hash = HashData(data, hashAlgorithm);
+            return CreateSignature(hash);
+        }
+
+        public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm)
+        {
+            if (data == null) { throw new ArgumentNullException("data"); }
+
+            return VerifyData(data, 0, data.Length, signature, hashAlgorithm);
+        }
+
+        public virtual bool VerifyData(byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm)
+        {
+            if (data == null) { throw new ArgumentNullException("data"); }
+            if (offset < 0 || offset > data.Length) { throw new ArgumentOutOfRangeException("offset"); }
+            if (count < 0 || count > data.Length - offset) { throw new ArgumentOutOfRangeException("count"); }
+            if (signature == null) { throw new ArgumentNullException("signature"); }
+            if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); }
+
+            byte[] hash = HashData(data, offset, count, hashAlgorithm);
+            return VerifySignature(hash, signature);
+        }
+
+        public virtual bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithm)
+        {
+            if (data == null) { throw new ArgumentNullException("data"); }
+            if (signature == null) { throw new ArgumentNullException("signature"); }
+            if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); }
+
+            byte[] hash = HashData(data, hashAlgorithm);
+            return VerifySignature(hash, signature);
+        }
+
         // We can provide a default implementation of FromXmlString because we require 
         // every DSA implementation to implement ImportParameters
         // All we have to do here is parse the XML.
@@ -187,5 +256,15 @@ namespace System.Security.Cryptography {
         abstract public DSAParameters ExportParameters(bool includePrivateParameters);
 
         abstract public void ImportParameters(DSAParameters parameters);
+
+        private static Exception DerivedClassMustOverride()
+        {
+            return new NotImplementedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+        }
+
+        internal static Exception HashAlgorithmNameNullOrEmpty()
+        {
+            return new ArgumentException(Environment.GetResourceString("Cryptography_HashAlgorithmNameNullOrEmpty"), "hashAlgorithm");
+        }
     }
 }
index 318b09813abdab62f3bfdc5d96b13250fac0c4d7..df23a26af107962222af0ff7b63843f7c09c637d 100644 (file)
@@ -268,6 +268,36 @@ namespace System.Security.Cryptography {
             return VerifyHash(rgbHash, null, rgbSignature);
         }
 
+        protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
+        {
+            // we're sealed and the base should have checked this before calling us
+            Contract.Assert(data != null);
+            Contract.Assert(offset >= 0 && offset <= data.Length);
+            Contract.Assert(count >= 0 && count <= data.Length - offset);
+            Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
+
+            if (hashAlgorithm != HashAlgorithmName.SHA1)
+            {
+                throw new CryptographicException(Environment.GetResourceString("Cryptography_UnknownHashAlgorithm", hashAlgorithm.Name));
+            }
+
+            return _sha1.ComputeHash(data, offset, count);
+        }
+
+        protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm)
+        {
+            // we're sealed and the base should have checked this before calling us
+            Contract.Assert(data != null);
+            Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
+
+            if (hashAlgorithm != HashAlgorithmName.SHA1)
+            {
+                throw new CryptographicException(Environment.GetResourceString("Cryptography_UnknownHashAlgorithm", hashAlgorithm.Name));
+            }
+
+            return _sha1.ComputeHash(data);
+        }
+
         [System.Security.SecuritySafeCritical]  // auto-generated
         public byte[] SignHash(byte[] rgbHash, string str) {
             if (rgbHash == null)
index 0bf87db770ef847b0f0fe74bcddf974ff0743486..0954818455914214f4a21c807ed7d00eea61d89b 100644 (file)
@@ -37,9 +37,10 @@ namespace System.Security.Cryptography {
     }
 
     [System.Runtime.InteropServices.ComVisible(true)]
-    public sealed class RSACryptoServiceProvider : RSA
+    public sealed partial class RSACryptoServiceProvider : RSA
         , ICspAsymmetricAlgorithm
     {
+#if !MONO
         private int _dwKeySize;
         private CspParameters  _parameters;
         private bool _randomKeyContainer;
@@ -47,13 +48,13 @@ namespace System.Security.Cryptography {
         private SafeProvHandle _safeProvHandle;
         [System.Security.SecurityCritical] // auto-generated
         private SafeKeyHandle _safeKeyHandle;
-
+#endif
         private static volatile CspProviderFlags s_UseMachineKeyStore = 0;
 
         //
         // QCalls
         //
-
+#if !MONO
         [System.Security.SecurityCritical]  // auto-generated
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
         [ResourceExposure(ResourceScope.None)]
@@ -194,7 +195,7 @@ namespace System.Security.Cryptography {
                 return null;
             }
         }
-
+#endif
         public override string SignatureAlgorithm {
             get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; }
         }
@@ -203,7 +204,7 @@ namespace System.Security.Cryptography {
             get { return (s_UseMachineKeyStore == CspProviderFlags.UseMachineKeyStore); }
             set { s_UseMachineKeyStore = (value ? CspProviderFlags.UseMachineKeyStore : 0); }
         }
-
+#if !MONO
         public bool PersistKeyInCsp {
             [System.Security.SecuritySafeCritical]  // auto-generated
             get {
@@ -502,7 +503,7 @@ namespace System.Security.Cryptography {
         private static bool IsPublic(RSAParameters rsaParams) {
             return (rsaParams.P == null);
         }
-        
+#endif
         //
         // Adapt new RSA abstraction to legacy RSACryptoServiceProvider surface area.
         //
@@ -524,10 +525,14 @@ namespace System.Security.Cryptography {
             Contract.Assert(count >= 0 && count <= data.Length);
             Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
 
+#if MONO
+            throw new NotImplementedException ();
+#else
             using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) {
                 Utils.HashData(hashHandle, data, offset, count);
                 return Utils.EndHash(hashHandle);
             }
+#endif
         }
 
         [SecuritySafeCritical]
@@ -536,6 +541,9 @@ namespace System.Security.Cryptography {
             Contract.Assert(data != null);
             Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
 
+#if MONO
+            throw new NotImplementedException ();
+#else
             using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) {
                 // Read the data 4KB at a time, providing similar read characteristics to a standard HashAlgorithm
                 byte[] buffer = new byte[4096];
@@ -549,6 +557,7 @@ namespace System.Security.Cryptography {
 
                 return Utils.EndHash(hashHandle);
             }
+#endif
         }
         
         private static int GetAlgorithmId(HashAlgorithmName hashAlgorithm) {
index 416b29f5079d35aaf8cb039aaf473c5a8eb09a66..674cdf23f61af1a894bd382375cb36d6a8a6ec59 100644 (file)
@@ -11,6 +11,7 @@ namespace System.Security.Cryptography {
     [System.Runtime.InteropServices.ComVisible(true)]
     public class RSAOAEPKeyExchangeDeformatter : AsymmetricKeyExchangeDeformatter {
         private RSA _rsaKey; // RSA Key value to do decrypt operation
+        private bool?  _rsaOverridesDecrypt;
 
         //
         // public constructors
@@ -42,8 +43,8 @@ namespace System.Security.Cryptography {
             if (_rsaKey == null)
                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey"));
 
-            if (_rsaKey is RSACryptoServiceProvider) {
-                return ((RSACryptoServiceProvider) _rsaKey).Decrypt(rgbData, true);
+            if (OverridesDecrypt) {
+                return _rsaKey.Decrypt(rgbData, RSAEncryptionPadding.OaepSHA1);
             } else {
                 return Utils.RsaOaepDecrypt(_rsaKey, SHA1.Create(), new PKCS1MaskGenerationMethod(), rgbData);
             }
@@ -54,6 +55,16 @@ namespace System.Security.Cryptography {
                 throw new ArgumentNullException("key");
             Contract.EndContractBlock();
             _rsaKey = (RSA) key;
+            _rsaOverridesDecrypt = default(bool?);
+        }
+
+        private bool OverridesDecrypt {
+            get {
+                if (!_rsaOverridesDecrypt.HasValue) {
+                    _rsaOverridesDecrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Decrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) });
+                }
+                return _rsaOverridesDecrypt.Value;
+            }
         }
     }
 }
index 68746fe1773aaabb5821daa458ea2c23cf158de6..a931c154cdee84a27f5e5eaa3acad7af3f70423f 100644 (file)
@@ -12,6 +12,7 @@ namespace System.Security.Cryptography {
     public class RSAOAEPKeyExchangeFormatter : AsymmetricKeyExchangeFormatter {
         private byte[] ParameterValue;
         private RSA _rsaKey;
+        private bool?  _rsaOverridesEncrypt;
         private RandomNumberGenerator RngValue;
 
         //
@@ -64,6 +65,7 @@ namespace System.Security.Cryptography {
                 throw new ArgumentNullException("key");
             Contract.EndContractBlock();
             _rsaKey = (RSA) key;
+            _rsaOverridesEncrypt = default(bool?);
         }
 
         [System.Security.SecuritySafeCritical]  // auto-generated
@@ -71,8 +73,8 @@ namespace System.Security.Cryptography {
             if (_rsaKey == null)
                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey"));
 
-            if (_rsaKey is RSACryptoServiceProvider) {
-                return ((RSACryptoServiceProvider) _rsaKey).Encrypt(rgbData, true);
+            if (OverridesEncrypt) {
+                return _rsaKey.Encrypt(rgbData, RSAEncryptionPadding.OaepSHA1);
             } else {
                 return Utils.RsaOaepEncrypt(_rsaKey, SHA1.Create(), new PKCS1MaskGenerationMethod(), RandomNumberGenerator.Create(), rgbData);
             }
@@ -81,5 +83,14 @@ namespace System.Security.Cryptography {
         public override byte[] CreateKeyExchange(byte[] rgbData, Type symAlgType) {
             return CreateKeyExchange(rgbData);
         }
+
+        private bool OverridesEncrypt {
+            get {
+                if (!_rsaOverridesEncrypt.HasValue) {
+                    _rsaOverridesEncrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Encrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) });
+                }
+                return _rsaOverridesEncrypt.Value;
+            }
+        }
     }
 }
index ed412c64dba41b8d6125c3c7f3bfe05271f21f58..ccd8570ada52f15cb5dd118d73663b304f212c0f 100644 (file)
@@ -11,6 +11,7 @@ namespace System.Security.Cryptography {
     [System.Runtime.InteropServices.ComVisible(true)]
     public class RSAPKCS1KeyExchangeDeformatter : AsymmetricKeyExchangeDeformatter {
         RSA _rsaKey;
+        bool?  _rsaOverridesDecrypt;
         RandomNumberGenerator RngValue;
 
         // Constructors
@@ -47,8 +48,8 @@ namespace System.Security.Cryptography {
                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey"));
 
             byte[] rgbOut;
-            if (_rsaKey is RSACryptoServiceProvider) {
-                rgbOut = ((RSACryptoServiceProvider) _rsaKey).Decrypt(rgbIn, false);
+            if (OverridesDecrypt) {
+                rgbOut = _rsaKey.Decrypt(rgbIn, RSAEncryptionPadding.Pkcs1);
             }
             else {
                 int i;
@@ -83,6 +84,16 @@ namespace System.Security.Cryptography {
                 throw new ArgumentNullException("key");
             Contract.EndContractBlock();
             _rsaKey = (RSA) key;
+            _rsaOverridesDecrypt = default(bool?);
+        }
+
+        private bool OverridesDecrypt {
+            get {
+                if (!_rsaOverridesDecrypt.HasValue) {
+                    _rsaOverridesDecrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Decrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) });
+                }
+                return _rsaOverridesDecrypt.Value;
+            }
         }
     }
 }
index 19f34b6d6fbaa914ff76b25ef6af67aee46b4644..188e55ce1c4acfc977eb85b8f38cac056af7cc32 100644 (file)
@@ -14,6 +14,7 @@ namespace System.Security.Cryptography {
     public class RSAPKCS1KeyExchangeFormatter : AsymmetricKeyExchangeFormatter {
         RandomNumberGenerator RngValue;
         RSA _rsaKey;
+        bool?  _rsaOverridesEncrypt;
 
         //
         // public constructors
@@ -50,6 +51,7 @@ namespace System.Security.Cryptography {
                 throw new ArgumentNullException("key");
             Contract.EndContractBlock();
             _rsaKey = (RSA) key;
+            _rsaOverridesEncrypt = default(bool?);
         }
 
         public override byte[] CreateKeyExchange(byte[] rgbData) {
@@ -62,8 +64,8 @@ namespace System.Security.Cryptography {
                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey"));
 
             byte[] rgbKeyEx;
-            if (_rsaKey is RSACryptoServiceProvider) {
-                rgbKeyEx = ((RSACryptoServiceProvider) _rsaKey).Encrypt(rgbData, false);
+            if (OverridesEncrypt) {
+                rgbKeyEx = _rsaKey.Encrypt(rgbData, RSAEncryptionPadding.Pkcs1);
             }
             else {
                 int cb = _rsaKey.KeySize/8;
@@ -101,5 +103,14 @@ namespace System.Security.Cryptography {
         public override byte[] CreateKeyExchange(byte[] rgbData, Type symAlgType) {
             return CreateKeyExchange(rgbData);
         }
+
+        private bool OverridesEncrypt {
+            get {
+                if (!_rsaOverridesEncrypt.HasValue) {
+                    _rsaOverridesEncrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Encrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) });
+                }
+                return _rsaOverridesEncrypt.Value;
+            }
+        }
     }
 }
index 01363fefbdd9af7e2ba30ee609abc430edc9f955..28ee8738639ca84fdb8294c804fe3aeaa7e41dab 100644 (file)
@@ -27,6 +27,7 @@ namespace System.Security.Cryptography {
 
         private RSA    _rsaKey; // RSA Key value to do decrypt operation
         private String _strOID; // OID value for the HASH algorithm
+        private bool?  _rsaOverridesVerifyHash;
 
         //
         // public constructors
@@ -49,6 +50,7 @@ namespace System.Security.Cryptography {
                 throw new ArgumentNullException("key");
             Contract.EndContractBlock();
             _rsaKey = (RSA) key;
+            _rsaOverridesVerifyHash = default(bool?);
         }
 
         public override void SetHashAlgorithm(String strName) {
@@ -70,15 +72,32 @@ namespace System.Security.Cryptography {
 
             // Two cases here -- if we are talking to the CSP version or if we are talking to some other RSA provider.
             if (_rsaKey is RSACryptoServiceProvider) {
+                // This path is kept around for desktop compat: in case someone is using this with a hash algorithm that's known to GetAlgIdFromOid but
+                // not from OidToHashAlgorithmName.
                 int calgHash = X509Utils.GetAlgIdFromOid(_strOID, OidGroup.HashAlgorithm);
                 return ((RSACryptoServiceProvider)_rsaKey).VerifyHash(rgbHash, calgHash, rgbSignature);
             }
+            else if (OverridesVerifyHash) {
+                HashAlgorithmName hashAlgorithmName = Utils.OidToHashAlgorithmName(_strOID);
+                return _rsaKey.VerifyHash(rgbHash, rgbSignature, hashAlgorithmName, RSASignaturePadding.Pkcs1);
+            }
             else {
+                // Fallback compat path for 3rd-party RSA classes that don't override VerifyHash()
+
                 byte[] pad = Utils.RsaPkcs1Padding(_rsaKey, CryptoConfig.EncodeOID(_strOID), rgbHash);
                 // Apply the public key to the signature data to get back the padded buffer actually signed.
                 // Compare the two buffers to see if they match; ignoring any leading zeros
                 return Utils.CompareBigIntArrays(_rsaKey.EncryptValue(rgbSignature), pad);
             }
         }
+
+        private bool OverridesVerifyHash {
+            get {
+                if (!_rsaOverridesVerifyHash.HasValue) {
+                    _rsaOverridesVerifyHash = Utils.DoesRsaKeyOverride(_rsaKey, "VerifyHash", new Type[] { typeof(byte[]), typeof(byte[]), typeof(HashAlgorithmName), typeof(RSASignaturePadding) });
+                }
+                return _rsaOverridesVerifyHash.Value;
+            }
+        }
     }
 }
index 249ea4b072c468c01031abf48083696419c1bbc6..9791242561098c983cdaf92203fbad5431a462ec 100644 (file)
@@ -19,6 +19,7 @@ namespace System.Security.Cryptography {
     public class RSAPKCS1SignatureFormatter : AsymmetricSignatureFormatter {
         private RSA    _rsaKey;
         private String _strOID;
+        private bool?  _rsaOverridesSignHash;
 
         //
         // public constructors
@@ -42,6 +43,7 @@ namespace System.Security.Cryptography {
                 throw new ArgumentNullException("key");
             Contract.EndContractBlock();
             _rsaKey = (RSA) key;
+            _rsaOverridesSignHash = default(bool?);
         }
 
         public override void SetHashAlgorithm(String strName) {
@@ -61,14 +63,31 @@ namespace System.Security.Cryptography {
 
             // Two cases here -- if we are talking to the CSP version or if we are talking to some other RSA provider.
             if (_rsaKey is RSACryptoServiceProvider) {
+                // This path is kept around for desktop compat: in case someone is using this with a hash algorithm that's known to GetAlgIdFromOid but
+                // not from OidToHashAlgorithmName.
                 int calgHash = X509Utils.GetAlgIdFromOid(_strOID, OidGroup.HashAlgorithm);
                 return ((RSACryptoServiceProvider)_rsaKey).SignHash(rgbHash, calgHash);
             }
+            else if (OverridesSignHash) {
+                HashAlgorithmName hashAlgorithmName = Utils.OidToHashAlgorithmName(_strOID);
+                return _rsaKey.SignHash(rgbHash, hashAlgorithmName, RSASignaturePadding.Pkcs1);
+            }
             else {
+                // Fallback compat path for 3rd-party RSA classes that don't override SignHash()
+
                 byte[] pad = Utils.RsaPkcs1Padding(_rsaKey, CryptoConfig.EncodeOID(_strOID), rgbHash);
                 // Create the signature by applying the private key to the padded buffer we just created.
                 return _rsaKey.DecryptValue(pad);
             }
         }
+
+        private bool OverridesSignHash {
+            get {
+                if (!_rsaOverridesSignHash.HasValue) {
+                    _rsaOverridesSignHash = Utils.DoesRsaKeyOverride(_rsaKey, "SignHash", new Type[] { typeof(byte[]), typeof(HashAlgorithmName), typeof(RSASignaturePadding) });
+                }
+                return _rsaOverridesSignHash.Value;
+            }
+        }
     }
 }
index f115e8afc39f82e5a9938938a9c2c11e7c72a0e3..330a0222f098b01ce6b7ad92b38318747007f418 100644 (file)
@@ -83,20 +83,52 @@ namespace System.Security.Cryptography {
         }
     }
 
-    internal class RSAPKCS1SHA1SignatureDescription : SignatureDescription {
-        public RSAPKCS1SHA1SignatureDescription() {
-            KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider";
-            DigestAlgorithm = "System.Security.Cryptography.SHA1CryptoServiceProvider";
+    internal abstract class RSAPKCS1SignatureDescription : SignatureDescription {
+        protected RSAPKCS1SignatureDescription(string hashAlgorithm, string digestAlgorithm) {
+            KeyAlgorithm = "System.Security.Cryptography.RSA";
+            DigestAlgorithm = digestAlgorithm;
             FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
             DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
+            _hashAlgorithm = hashAlgorithm;
+        }
+        public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) {
+            AsymmetricSignatureDeformatter item = base.CreateDeformatter(key);
+            item.SetHashAlgorithm(_hashAlgorithm);
+            return item;
         }
 
-        public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) {
-            AsymmetricSignatureDeformatter item = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm);
-            item.SetKey(key);
-            item.SetHashAlgorithm("SHA1");
+        public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) {
+            AsymmetricSignatureFormatter item = base.CreateFormatter(key);
+            item.SetHashAlgorithm(_hashAlgorithm);
             return item;
         }
+
+        private string _hashAlgorithm;
+    }
+
+    internal class RSAPKCS1SHA1SignatureDescription : RSAPKCS1SignatureDescription {
+        public RSAPKCS1SHA1SignatureDescription()
+            : base("SHA1", "System.Security.Cryptography.SHA1Cng") {
+        }
+    }
+
+    internal class RSAPKCS1SHA256SignatureDescription : RSAPKCS1SignatureDescription {
+        public RSAPKCS1SHA256SignatureDescription()
+            : base("SHA256", "System.Security.Cryptography.SHA256Cng") {
+        }
+    }
+
+    internal class RSAPKCS1SHA384SignatureDescription : RSAPKCS1SignatureDescription {
+        public RSAPKCS1SHA384SignatureDescription()
+            : base("SHA384", "System.Security.Cryptography.SHA384Cng") {
+        }
+    }
+
+    internal class RSAPKCS1SHA512SignatureDescription : RSAPKCS1SignatureDescription {
+        public RSAPKCS1SHA512SignatureDescription()
+            : base("SHA512", "System.Security.Cryptography.SHA512Cng") {
+        }
     }
 
     internal class DSASignatureDescription : SignatureDescription {
index e8a95fc3be9bc98430dde2f658a65709cca7a3da..cc08a62a05957c141ee98fd95ad107e1053f1d95 100644 (file)
@@ -16,6 +16,7 @@ namespace System.Security.Cryptography
 {
     using Microsoft.Win32;
     using System.IO;
+    using System.Reflection;
     using System.Globalization;
     using System.Runtime.CompilerServices;
     using System.Runtime.InteropServices;
@@ -1017,7 +1018,74 @@ namespace System.Security.Cryptography
         [ResourceExposure(ResourceScope.None)]  // Creates a process resource, but it can't be scoped.
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
         internal static extern SafeHashHandle CreateHash(SafeProvHandle hProv, int algid);
+#endif
+        internal static HashAlgorithmName OidToHashAlgorithmName(string oid)
+        {
+            switch (oid)
+            {
+                case Constants.OID_OIWSEC_SHA1:
+                    return HashAlgorithmName.SHA1;
+
+                case Constants.OID_OIWSEC_SHA256:
+                    return HashAlgorithmName.SHA256;
 
+                case Constants.OID_OIWSEC_SHA384:
+                    return HashAlgorithmName.SHA384;
+
+                case Constants.OID_OIWSEC_SHA512:
+                    return HashAlgorithmName.SHA512;
+
+                default:
+                    throw new NotSupportedException();
+            }
+        }
+
+        //
+        // Backward-compat hack for third-party RSA-derived classes:
+        // 
+        // Because the SignHash()/VerifyHash()/Encrypt()/Decrypt() methods are new on RSA, we may 
+        // encounter older third-party RSA-derived classes that don't override them
+        // (and if they don't override them, these methods will throw since they are effectively abstract methods that had to declared non-abstract
+        // for backward compat reasons.)
+        //
+        internal static bool DoesRsaKeyOverride(RSA rsaKey, string methodName, Type[] parameterTypes)
+        {
+            // A fast-path check for the common cases where we know we implemented the overrides.
+            Type t = rsaKey.GetType();
+            if (rsaKey is RSACryptoServiceProvider)
+            {
+#if DEBUG
+                // On checked builds, do the slow-path check anyway so it gets exercised.
+                bool foundOverride = DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes);
+                BCLDebug.Assert(foundOverride, "RSACryptoServiceProvider expected to override " + methodName);
+#endif
+                return true;
+            }
+
+            string fullName = t.FullName;
+            if (fullName == "System.Security.Cryptography.RSACng")
+            {
+#if DEBUG
+                // On checked builds, do the slow-path check anyway so it gets exercised.
+                bool foundOverride = DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes);
+                BCLDebug.Assert(foundOverride, "RSACng expected to override " + methodName);
+#endif
+                return true;
+            }
+            return DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes);
+        }
+
+        private static bool DoesRsaKeyOverrideSlowPath(Type t, string methodName, Type[] parameterTypes)
+        {
+            MethodInfo method = t.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null);
+            BCLDebug.Assert(method != null, "method != null"); 
+            Type declaringType = method.DeclaringType;
+            if (declaringType == typeof(RSA))
+                return false;
+
+            return true;
+        }
+#if !MONO
         [System.Security.SecurityCritical]  // auto-generated
         [ResourceExposure(ResourceScope.None)]
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
index 23f747c04231971c50c00f0114fb22d2ee9b326c..e730084e191969aa3e1fc3376d290738e5d782af 100644 (file)
@@ -159,7 +159,7 @@ namespace System.Security.Cryptography.X509Certificates
                 if (group != OidGroup.AllGroups) {
                     IntPtr allGroupOidInfo = CryptFindOIDInfo(keyType, rawKey, OidGroup.AllGroups);
                     if (allGroupOidInfo != IntPtr.Zero) {
-                        return (CRYPT_OID_INFO)Marshal.PtrToStructure(fullOidInfo, typeof(CRYPT_OID_INFO));
+                        return (CRYPT_OID_INFO)Marshal.PtrToStructure(allGroupOidInfo, typeof(CRYPT_OID_INFO));
                     }
                 }
 
index 02ef088b5e67b3c0f83d136fcac8d765b1f64847..db35ac502b007c51c1cd1ccf4ce0bab61f5331ea 100644 (file)
@@ -24,9 +24,9 @@ namespace System.Security.Permissions {
     using System.Runtime.Versioning;
     using System.Diagnostics.Contracts;
 
-[Serializable]
+    [Serializable]
     [Flags]
-[System.Runtime.InteropServices.ComVisible(true)]
+    [System.Runtime.InteropServices.ComVisible(true)]
     public enum FileIOPermissionAccess
     {
         NoAccess = 0x00,
@@ -36,9 +36,8 @@ namespace System.Security.Permissions {
         PathDiscovery = 0x08,
         AllAccess = 0x0F,
     }
-    
-    
-[System.Runtime.InteropServices.ComVisible(true)]
+
+    [System.Runtime.InteropServices.ComVisible(true)]
     [Serializable]
     sealed public class FileIOPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
     {
@@ -51,7 +50,7 @@ namespace System.Security.Permissions {
         [OptionalField(VersionAdded = 2)]
         private FileIOAccess m_changeAcl;
         private bool m_unrestricted;
-        
+
         public FileIOPermission(PermissionState state)
         {
             if (state == PermissionState.Unrestricted)
@@ -67,91 +66,91 @@ namespace System.Security.Permissions {
                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
             }
         }
-        
+
         [System.Security.SecuritySafeCritical]  // auto-generated
-        public FileIOPermission( FileIOPermissionAccess access, String path )
+        public FileIOPermission(FileIOPermissionAccess access, String path)
         {
-            VerifyAccess( access );
-        
+            VerifyAccess(access);
+
             String[] pathList = new String[] { path };
-            AddPathList( access, pathList, false, true, false );
+            AddPathList(access, pathList, false, true, false);
         }
-        
+
         [System.Security.SecuritySafeCritical]  // auto-generated
-        public FileIOPermission( FileIOPermissionAccess access, String[] pathList )
+        public FileIOPermission(FileIOPermissionAccess access, String[] pathList)
         {
-            VerifyAccess( access );
-        
-            AddPathList( access, pathList, false, true, false );
+            VerifyAccess(access);
+
+            AddPathList(access, pathList, false, true, false);
         }
 
 #if FEATURE_MACL
         [System.Security.SecuritySafeCritical]  // auto-generated
-        public FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String path )
+        public FileIOPermission(FileIOPermissionAccess access, AccessControlActions control, String path)
         {
-            VerifyAccess( access );
-        
+            VerifyAccess(access);
+
             String[] pathList = new String[] { path };
-            AddPathList( access, control, pathList, false, true, false );
+            AddPathList(access, control, pathList, false, true, false);
         }
-        
+
         [System.Security.SecuritySafeCritical]  // auto-generated
-        public FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String[] pathList )
-            : this( access, control, pathList, true, true )
+        public FileIOPermission(FileIOPermissionAccess access, AccessControlActions control, String[] pathList)
+            : this(access, control, pathList, true, true)
         {
         }
 #endif
 
         [System.Security.SecurityCritical]  // auto-generated
-        internal FileIOPermission( FileIOPermissionAccess access, String[] pathList, bool checkForDuplicates, bool needFullPath )
+        internal FileIOPermission(FileIOPermissionAccess access, String[] pathList, bool checkForDuplicates, bool needFullPath)
         {
-            VerifyAccess( access );
-        
-            AddPathList( access, pathList, checkForDuplicates, needFullPath, true );
+            VerifyAccess(access);
+
+            AddPathList(access, pathList, checkForDuplicates, needFullPath, true);
         }
 
 #if FEATURE_MACL
         [System.Security.SecurityCritical]  // auto-generated
-        internal FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates, bool needFullPath )
+        internal FileIOPermission(FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates, bool needFullPath)
         {
-            VerifyAccess( access );
-        
-            AddPathList( access, control, pathList, checkForDuplicates, needFullPath, true );
+            VerifyAccess(access);
+
+            AddPathList(access, control, pathList, checkForDuplicates, needFullPath, true);
         }
 #endif
 
-        public void SetPathList( FileIOPermissionAccess access, String path )
+        public void SetPathList(FileIOPermissionAccess access, String path)
         {
             String[] pathList;
-            if(path == null)
-                pathList = new String[] {};
+            if (path == null)
+                pathList = new String[] { };
             else
                 pathList = new String[] { path };
-            SetPathList( access, pathList, false );
+            SetPathList(access, pathList, false);
         }
-            
-        public void SetPathList( FileIOPermissionAccess access, String[] pathList )
+
+        public void SetPathList(FileIOPermissionAccess access, String[] pathList)
         {
-            SetPathList( access, pathList, true );
+            SetPathList(access, pathList, true);
         }
 
-        internal void SetPathList( FileIOPermissionAccess access, 
-            String[] pathList, bool checkForDuplicates )
+        internal void SetPathList(FileIOPermissionAccess access,
+            String[] pathList, bool checkForDuplicates)
         {
-            SetPathList( access, AccessControlActions.None, pathList, checkForDuplicates );
+            SetPathList(access, AccessControlActions.None, pathList, checkForDuplicates);
         }
 
         [System.Security.SecuritySafeCritical]  // auto-generated
-        internal void SetPathList( FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates )
+        internal void SetPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates)
         {
-            VerifyAccess( access );
-            
+            VerifyAccess(access);
+
             if ((access & FileIOPermissionAccess.Read) != 0)
                 m_read = null;
-            
+
             if ((access & FileIOPermissionAccess.Write) != 0)
                 m_write = null;
-    
+
             if ((access & FileIOPermissionAccess.Append) != 0)
                 m_append = null;
 
@@ -168,36 +167,36 @@ namespace System.Security.Permissions {
             m_viewAcl = null;
             m_changeAcl = null;
 #endif
-            
+
             m_unrestricted = false;
 #if FEATURE_MACL
-            AddPathList( access, control, pathList, checkForDuplicates, true, true );
+            AddPathList(access, control, pathList, checkForDuplicates, true, true);
 #else
             AddPathList( access, pathList, checkForDuplicates, true, true );
 #endif
         }
 
         [System.Security.SecuritySafeCritical]  // auto-generated
-        public void AddPathList( FileIOPermissionAccess access, String path )
+        public void AddPathList(FileIOPermissionAccess access, String path)
         {
             String[] pathList;
-            if(path == null)
-                pathList = new String[] {};
+            if (path == null)
+                pathList = new String[] { };
             else
                 pathList = new String[] { path };
-            AddPathList( access, pathList, false, true, false );
+            AddPathList(access, pathList, false, true, false);
         }
 
         [System.Security.SecuritySafeCritical]  // auto-generated
-        public void AddPathList( FileIOPermissionAccess access, String[] pathList )
+        public void AddPathList(FileIOPermissionAccess access, String[] pathList)
         {
-            AddPathList( access, pathList, true, true, true );
+            AddPathList(access, pathList, true, true, true);
         }
 
         [System.Security.SecurityCritical]  // auto-generated
-        internal void AddPathList( FileIOPermissionAccess access, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList )
+        internal void AddPathList(FileIOPermissionAccess access, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList)
         {
-            AddPathList( access, AccessControlActions.None, pathListOrig, checkForDuplicates, needFullPath, copyPathList );
+            AddPathList(access, AccessControlActions.None, pathListOrig, checkForDuplicates, needFullPath, copyPathList);
         }
 
         [System.Security.SecurityCritical]  // auto-generated
@@ -205,65 +204,73 @@ namespace System.Security.Permissions {
         {
             if (pathListOrig == null)
             {
-                throw new ArgumentNullException( "pathList" );    
+                throw new ArgumentNullException("pathList");
             }
             if (pathListOrig.Length == 0)
             {
-                throw new ArgumentException( Environment.GetResourceString("Argument_EmptyPath" ));    
+                throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
             }
             Contract.EndContractBlock();
             // @
 
             VerifyAccess(access);
-                
+
             if (m_unrestricted)
                 return;
 
             String[] pathList = pathListOrig;
-            if(copyPathList)
+            if (copyPathList)
             {
                 // Make a copy of pathList (in case its value changes after we check for illegal chars)
                 pathList = new String[pathListOrig.Length];
                 Array.Copy(pathListOrig, pathList, pathListOrig.Length);
             }
 
-            CheckIllegalCharacters( pathList );
+            // If we need the full path the standard illegal characters will be checked in StringExpressionSet.
+            CheckIllegalCharacters(pathList, onlyCheckExtras: needFullPath);
+
+            // StringExpressionSet will do minor normalization, trimming spaces and replacing alternate
+            // directory separators. It will make an attemt to expand short file names and will check
+            // for standard colon placement.
+            //
+            // If needFullPath is true it will call NormalizePath- which performs short name expansion
+            // and does the normal validity checks.
             ArrayList pathArrayList = StringExpressionSet.CreateListFromExpressions(pathList, needFullPath);
-            
+
             if ((access & FileIOPermissionAccess.Read) != 0)
             {
                 if (m_read == null)
                 {
                     m_read = new FileIOAccess();
                 }
-                m_read.AddExpressions( pathArrayList, checkForDuplicates);
+                m_read.AddExpressions(pathArrayList, checkForDuplicates);
             }
-            
+
             if ((access & FileIOPermissionAccess.Write) != 0)
             {
                 if (m_write == null)
                 {
                     m_write = new FileIOAccess();
                 }
-                m_write.AddExpressions( pathArrayList, checkForDuplicates);
+                m_write.AddExpressions(pathArrayList, checkForDuplicates);
             }
-    
+
             if ((access & FileIOPermissionAccess.Append) != 0)
             {
                 if (m_append == null)
                 {
                     m_append = new FileIOAccess();
                 }
-                m_append.AddExpressions( pathArrayList, checkForDuplicates);
+                m_append.AddExpressions(pathArrayList, checkForDuplicates);
             }
 
             if ((access & FileIOPermissionAccess.PathDiscovery) != 0)
             {
                 if (m_pathDiscovery == null)
                 {
-                    m_pathDiscovery = new FileIOAccess( true );
+                    m_pathDiscovery = new FileIOAccess(true);
                 }
-                m_pathDiscovery.AddExpressions( pathArrayList, checkForDuplicates);
+                m_pathDiscovery.AddExpressions(pathArrayList, checkForDuplicates);
             }
 
 #if FEATURE_MACL
@@ -273,7 +280,7 @@ namespace System.Security.Permissions {
                 {
                     m_viewAcl = new FileIOAccess();
                 }
-                m_viewAcl.AddExpressions( pathArrayList, checkForDuplicates);
+                m_viewAcl.AddExpressions(pathArrayList, checkForDuplicates);
             }
 
             if ((control & AccessControlActions.Change) != 0)
@@ -282,18 +289,18 @@ namespace System.Security.Permissions {
                 {
                     m_changeAcl = new FileIOAccess();
                 }
-                m_changeAcl.AddExpressions( pathArrayList, checkForDuplicates);
+                m_changeAcl.AddExpressions(pathArrayList, checkForDuplicates);
             }
 #endif
         }
-        
+
         [SecuritySafeCritical]
-        public String[] GetPathList( FileIOPermissionAccess access )
+        public String[] GetPathList(FileIOPermissionAccess access)
         {
-            VerifyAccess( access );
-            ExclusiveAccess( access );
-    
-            if (AccessIsSet( access, FileIOPermissionAccess.Read ))
+            VerifyAccess(access);
+            ExclusiveAccess(access);
+
+            if (AccessIsSet(access, FileIOPermissionAccess.Read))
             {
                 if (m_read == null)
                 {
@@ -301,8 +308,8 @@ namespace System.Security.Permissions {
                 }
                 return m_read.ToStringArray();
             }
-            
-            if (AccessIsSet( access, FileIOPermissionAccess.Write ))
+
+            if (AccessIsSet(access, FileIOPermissionAccess.Write))
             {
                 if (m_write == null)
                 {
@@ -310,8 +317,8 @@ namespace System.Security.Permissions {
                 }
                 return m_write.ToStringArray();
             }
-    
-            if (AccessIsSet( access, FileIOPermissionAccess.Append ))
+
+            if (AccessIsSet(access, FileIOPermissionAccess.Append))
             {
                 if (m_append == null)
                 {
@@ -319,8 +326,8 @@ namespace System.Security.Permissions {
                 }
                 return m_append.ToStringArray();
             }
-            
-            if (AccessIsSet( access, FileIOPermissionAccess.PathDiscovery ))
+
+            if (AccessIsSet(access, FileIOPermissionAccess.PathDiscovery))
             {
                 if (m_pathDiscovery == null)
                 {
@@ -330,10 +337,10 @@ namespace System.Security.Permissions {
             }
 
             // not reached
-            
+
             return null;
         }
-        
+
 
         public FileIOPermissionAccess AllLocalFiles
         {
@@ -341,19 +348,19 @@ namespace System.Security.Permissions {
             {
                 if (m_unrestricted)
                     return FileIOPermissionAccess.AllAccess;
-            
+
                 FileIOPermissionAccess access = FileIOPermissionAccess.NoAccess;
-                
+
                 if (m_read != null && m_read.AllLocalFiles)
                 {
                     access |= FileIOPermissionAccess.Read;
                 }
-                
+
                 if (m_write != null && m_write.AllLocalFiles)
                 {
                     access |= FileIOPermissionAccess.Write;
                 }
-                
+
                 if (m_append != null && m_append.AllLocalFiles)
                 {
                     access |= FileIOPermissionAccess.Append;
@@ -363,17 +370,17 @@ namespace System.Security.Permissions {
                 {
                     access |= FileIOPermissionAccess.PathDiscovery;
                 }
-                
+
                 return access;
             }
-            
+
             set
             {
                 if ((value & FileIOPermissionAccess.Read) != 0)
                 {
                     if (m_read == null)
                         m_read = new FileIOAccess();
-                        
+
                     m_read.AllLocalFiles = true;
                 }
                 else
@@ -381,12 +388,12 @@ namespace System.Security.Permissions {
                     if (m_read != null)
                         m_read.AllLocalFiles = false;
                 }
-                
+
                 if ((value & FileIOPermissionAccess.Write) != 0)
                 {
                     if (m_write == null)
                         m_write = new FileIOAccess();
-                        
+
                     m_write.AllLocalFiles = true;
                 }
                 else
@@ -394,12 +401,12 @@ namespace System.Security.Permissions {
                     if (m_write != null)
                         m_write.AllLocalFiles = false;
                 }
-                
+
                 if ((value & FileIOPermissionAccess.Append) != 0)
                 {
                     if (m_append == null)
                         m_append = new FileIOAccess();
-                        
+
                     m_append.AllLocalFiles = true;
                 }
                 else
@@ -411,8 +418,8 @@ namespace System.Security.Permissions {
                 if ((value & FileIOPermissionAccess.PathDiscovery) != 0)
                 {
                     if (m_pathDiscovery == null)
-                        m_pathDiscovery = new FileIOAccess( true );
-                        
+                        m_pathDiscovery = new FileIOAccess(true);
+
                     m_pathDiscovery.AllLocalFiles = true;
                 }
                 else
@@ -423,31 +430,31 @@ namespace System.Security.Permissions {
 
             }
         }
-        
+
         public FileIOPermissionAccess AllFiles
         {
             get
             {
                 if (m_unrestricted)
                     return FileIOPermissionAccess.AllAccess;
-            
+
                 FileIOPermissionAccess access = FileIOPermissionAccess.NoAccess;
-                
+
                 if (m_read != null && m_read.AllFiles)
                 {
                     access |= FileIOPermissionAccess.Read;
                 }
-                
+
                 if (m_write != null && m_write.AllFiles)
                 {
                     access |= FileIOPermissionAccess.Write;
                 }
-                
+
                 if (m_append != null && m_append.AllFiles)
                 {
                     access |= FileIOPermissionAccess.Append;
                 }
-                
+
                 if (m_pathDiscovery != null && m_pathDiscovery.AllFiles)
                 {
                     access |= FileIOPermissionAccess.PathDiscovery;
@@ -455,7 +462,7 @@ namespace System.Security.Permissions {
 
                 return access;
             }
-            
+
             set
             {
                 if (value == FileIOPermissionAccess.AllAccess)
@@ -463,12 +470,12 @@ namespace System.Security.Permissions {
                     m_unrestricted = true;
                     return;
                 }
-            
+
                 if ((value & FileIOPermissionAccess.Read) != 0)
                 {
                     if (m_read == null)
                         m_read = new FileIOAccess();
-                        
+
                     m_read.AllFiles = true;
                 }
                 else
@@ -476,12 +483,12 @@ namespace System.Security.Permissions {
                     if (m_read != null)
                         m_read.AllFiles = false;
                 }
-                
+
                 if ((value & FileIOPermissionAccess.Write) != 0)
                 {
                     if (m_write == null)
                         m_write = new FileIOAccess();
-                        
+
                     m_write.AllFiles = true;
                 }
                 else
@@ -489,12 +496,12 @@ namespace System.Security.Permissions {
                     if (m_write != null)
                         m_write.AllFiles = false;
                 }
-                
+
                 if ((value & FileIOPermissionAccess.Append) != 0)
                 {
                     if (m_append == null)
                         m_append = new FileIOAccess();
-                        
+
                     m_append.AllFiles = true;
                 }
                 else
@@ -506,8 +513,8 @@ namespace System.Security.Permissions {
                 if ((value & FileIOPermissionAccess.PathDiscovery) != 0)
                 {
                     if (m_pathDiscovery == null)
-                        m_pathDiscovery = new FileIOAccess( true );
-                        
+                        m_pathDiscovery = new FileIOAccess(true);
+
                     m_pathDiscovery.AllFiles = true;
                 }
                 else
@@ -517,42 +524,70 @@ namespace System.Security.Permissions {
                 }
 
             }
-        }        
-        
+        }
+
         [Pure]
-        private static void VerifyAccess( FileIOPermissionAccess access )
+        private static void VerifyAccess(FileIOPermissionAccess access)
         {
             if ((access & ~FileIOPermissionAccess.AllAccess) != 0)
                 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)access));
         }
-        
+
         [Pure]
-        private static void ExclusiveAccess( FileIOPermissionAccess access )
+        private static void ExclusiveAccess(FileIOPermissionAccess access)
         {
             if (access == FileIOPermissionAccess.NoAccess)
             {
-                throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") ); 
+                throw new ArgumentException(Environment.GetResourceString("Arg_EnumNotSingleFlag"));
             }
-    
-            if (((int) access & ((int)access-1)) != 0)
+
+            if (((int)access & ((int)access - 1)) != 0)
             {
-                throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") ); 
+                throw new ArgumentException(Environment.GetResourceString("Arg_EnumNotSingleFlag"));
             }
         }
 
-        private static void CheckIllegalCharacters( String[] str )
+        private static void CheckIllegalCharacters(String[] str, bool onlyCheckExtras)
         {
             for (int i = 0; i < str.Length; ++i)
             {
-                Path.CheckInvalidPathChars(str[i], true);
+                // FileIOPermission doesn't allow for normalizing across various volume names. This means "C:\" and
+                // "\\?\C:\" won't be considered correctly. In addition there are many other aliases for the volume
+                // besides "C:" such as (in one concrete example) "\\?\Harddisk0Partition2\", "\\?\HarddiskVolume6\",
+                // "\\?\Volume{d1655348-0000-0000-0000-f01500000000}\", etc.
+                //
+                // We'll continue to explicitly block extended syntax here by disallowing wildcards no matter where
+                // they occur in the string (e.g. \\?\ isn't ok)
+                if (CheckExtraPathCharacters(str[i]))
+                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
+
+                if (!onlyCheckExtras)
+                    Path.CheckInvalidPathChars(str[i]);
             }
         }
 
-        private static bool AccessIsSet( FileIOPermissionAccess access, FileIOPermissionAccess question )
+        /// <summary>
+        /// Check for ?,* and null, ignoring extended syntax.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private unsafe static bool CheckExtraPathCharacters(string path)
+        {
+            char currentChar;
+            for (int i = 0; i < path.Length; i++)
+            {
+                currentChar = path[i];
+
+                // We also check for null here as StringExpressionSet will trim it out. (Ensuring we still throw as we always have.)
+                if (currentChar == '*' || currentChar == '?' || currentChar == '\0') return true;
+            }
+            return false;
+        }
+
+        private static bool AccessIsSet(FileIOPermissionAccess access, FileIOPermissionAccess question)
         {
             return (access & question) != 0;
         }
-        
+
         private bool IsEmpty()
         {
             return (!m_unrestricted &&
@@ -563,24 +598,24 @@ namespace System.Security.Permissions {
                     (this.m_viewAcl == null || this.m_viewAcl.IsEmpty()) &&
                     (this.m_changeAcl == null || this.m_changeAcl.IsEmpty()));
         }
-        
+
         //------------------------------------------------------
         //
         // CODEACCESSPERMISSION IMPLEMENTATION
         //
         //------------------------------------------------------
-        
+
         public bool IsUnrestricted()
         {
             return m_unrestricted;
         }
-        
+
         //------------------------------------------------------
         //
         // IPERMISSION IMPLEMENTATION
         //
         //------------------------------------------------------
-        
+
         public override bool IsSubsetOf(IPermission target)
         {
             if (target == null)
@@ -597,14 +632,14 @@ namespace System.Security.Permissions {
             else if (this.IsUnrestricted())
                 return false;
             else
-                return ((this.m_read == null || this.m_read.IsSubsetOf( operand.m_read )) &&
-                        (this.m_write == null || this.m_write.IsSubsetOf( operand.m_write )) &&
-                        (this.m_append == null || this.m_append.IsSubsetOf( operand.m_append )) &&
-                        (this.m_pathDiscovery == null || this.m_pathDiscovery.IsSubsetOf( operand.m_pathDiscovery )) &&
-                        (this.m_viewAcl == null || this.m_viewAcl.IsSubsetOf( operand.m_viewAcl )) &&
-                        (this.m_changeAcl == null || this.m_changeAcl.IsSubsetOf( operand.m_changeAcl )));
+                return ((this.m_read == null || this.m_read.IsSubsetOf(operand.m_read)) &&
+                        (this.m_write == null || this.m_write.IsSubsetOf(operand.m_write)) &&
+                        (this.m_append == null || this.m_append.IsSubsetOf(operand.m_append)) &&
+                        (this.m_pathDiscovery == null || this.m_pathDiscovery.IsSubsetOf(operand.m_pathDiscovery)) &&
+                        (this.m_viewAcl == null || this.m_viewAcl.IsSubsetOf(operand.m_viewAcl)) &&
+                        (this.m_changeAcl == null || this.m_changeAcl.IsSubsetOf(operand.m_changeAcl)));
         }
-      
+
         public override IPermission Intersect(IPermission target)
         {
             if (target == null)
@@ -622,18 +657,18 @@ namespace System.Security.Permissions {
             {
                 return target.Copy();
             }
-    
+
             if (operand.IsUnrestricted())
             {
                 return this.Copy();
             }
-            
-            FileIOAccess intersectRead = this.m_read == null ? null : this.m_read.Intersect( operand.m_read );
-            FileIOAccess intersectWrite = this.m_write == null ? null : this.m_write.Intersect( operand.m_write );
-            FileIOAccess intersectAppend = this.m_append == null ? null : this.m_append.Intersect( operand.m_append );
-            FileIOAccess intersectPathDiscovery = this.m_pathDiscovery == null ? null : this.m_pathDiscovery.Intersect( operand.m_pathDiscovery );
-            FileIOAccess intersectViewAcl = this.m_viewAcl == null ? null : this.m_viewAcl.Intersect( operand.m_viewAcl );
-            FileIOAccess intersectChangeAcl = this.m_changeAcl == null ? null : this.m_changeAcl.Intersect( operand.m_changeAcl );
+
+            FileIOAccess intersectRead = this.m_read == null ? null : this.m_read.Intersect(operand.m_read);
+            FileIOAccess intersectWrite = this.m_write == null ? null : this.m_write.Intersect(operand.m_write);
+            FileIOAccess intersectAppend = this.m_append == null ? null : this.m_append.Intersect(operand.m_append);
+            FileIOAccess intersectPathDiscovery = this.m_pathDiscovery == null ? null : this.m_pathDiscovery.Intersect(operand.m_pathDiscovery);
+            FileIOAccess intersectViewAcl = this.m_viewAcl == null ? null : this.m_viewAcl.Intersect(operand.m_viewAcl);
+            FileIOAccess intersectChangeAcl = this.m_changeAcl == null ? null : this.m_changeAcl.Intersect(operand.m_changeAcl);
 
             if ((intersectRead == null || intersectRead.IsEmpty()) &&
                 (intersectWrite == null || intersectWrite.IsEmpty()) &&
@@ -644,7 +679,7 @@ namespace System.Security.Permissions {
             {
                 return null;
             }
-            
+
             FileIOPermission intersectPermission = new FileIOPermission(PermissionState.None);
             intersectPermission.m_unrestricted = false;
             intersectPermission.m_read = intersectRead;
@@ -653,10 +688,10 @@ namespace System.Security.Permissions {
             intersectPermission.m_pathDiscovery = intersectPathDiscovery;
             intersectPermission.m_viewAcl = intersectViewAcl;
             intersectPermission.m_changeAcl = intersectChangeAcl;
-            
+
             return intersectPermission;
         }
-        
+
         public override IPermission Union(IPermission other)
         {
             if (other == null)
@@ -670,19 +705,19 @@ namespace System.Security.Permissions {
             {
                 throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
             }
-    
+
             if (this.IsUnrestricted() || operand.IsUnrestricted())
             {
-                return new FileIOPermission( PermissionState.Unrestricted );
+                return new FileIOPermission(PermissionState.Unrestricted);
             }
-    
-            FileIOAccess unionRead = this.m_read == null ? operand.m_read : this.m_read.Union( operand.m_read );
-            FileIOAccess unionWrite = this.m_write == null ? operand.m_write : this.m_write.Union( operand.m_write );
-            FileIOAccess unionAppend = this.m_append == null ? operand.m_append : this.m_append.Union( operand.m_append );
-            FileIOAccess unionPathDiscovery = this.m_pathDiscovery == null ? operand.m_pathDiscovery : this.m_pathDiscovery.Union( operand.m_pathDiscovery );
-            FileIOAccess unionViewAcl = this.m_viewAcl == null ? operand.m_viewAcl : this.m_viewAcl.Union( operand.m_viewAcl );
-            FileIOAccess unionChangeAcl = this.m_changeAcl == null ? operand.m_changeAcl : this.m_changeAcl.Union( operand.m_changeAcl );
-            
+
+            FileIOAccess unionRead = this.m_read == null ? operand.m_read : this.m_read.Union(operand.m_read);
+            FileIOAccess unionWrite = this.m_write == null ? operand.m_write : this.m_write.Union(operand.m_write);
+            FileIOAccess unionAppend = this.m_append == null ? operand.m_append : this.m_append.Union(operand.m_append);
+            FileIOAccess unionPathDiscovery = this.m_pathDiscovery == null ? operand.m_pathDiscovery : this.m_pathDiscovery.Union(operand.m_pathDiscovery);
+            FileIOAccess unionViewAcl = this.m_viewAcl == null ? operand.m_viewAcl : this.m_viewAcl.Union(operand.m_viewAcl);
+            FileIOAccess unionChangeAcl = this.m_changeAcl == null ? operand.m_changeAcl : this.m_changeAcl.Union(operand.m_changeAcl);
+
             if ((unionRead == null || unionRead.IsEmpty()) &&
                 (unionWrite == null || unionWrite.IsEmpty()) &&
                 (unionAppend == null || unionAppend.IsEmpty()) &&
@@ -692,7 +727,7 @@ namespace System.Security.Permissions {
             {
                 return null;
             }
-            
+
             FileIOPermission unionPermission = new FileIOPermission(PermissionState.None);
             unionPermission.m_unrestricted = false;
             unionPermission.m_read = unionRead;
@@ -702,9 +737,9 @@ namespace System.Security.Permissions {
             unionPermission.m_viewAcl = unionViewAcl;
             unionPermission.m_changeAcl = unionChangeAcl;
 
-            return unionPermission;    
+            return unionPermission;
         }
-        
+
         public override IPermission Copy()
         {
             FileIOPermission copy = new FileIOPermission(PermissionState.None);
@@ -740,97 +775,97 @@ namespace System.Security.Permissions {
                     copy.m_changeAcl = this.m_changeAcl.Copy();
                 }
             }
-            return copy;   
+            return copy;
         }
-   
+
 #if FEATURE_CAS_POLICY
         public override SecurityElement ToXml()
         {
-            SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.FileIOPermission" );
+            SecurityElement esd = CodeAccessPermission.CreatePermissionElement(this, "System.Security.Permissions.FileIOPermission");
             if (!IsUnrestricted())
             {
                 if (this.m_read != null && !this.m_read.IsEmpty())
                 {
-                    esd.AddAttribute( "Read", SecurityElement.Escape( m_read.ToString() ) );
+                    esd.AddAttribute("Read", SecurityElement.Escape(m_read.ToString()));
                 }
                 if (this.m_write != null && !this.m_write.IsEmpty())
                 {
-                    esd.AddAttribute( "Write", SecurityElement.Escape( m_write.ToString() ) );
+                    esd.AddAttribute("Write", SecurityElement.Escape(m_write.ToString()));
                 }
                 if (this.m_append != null && !this.m_append.IsEmpty())
                 {
-                    esd.AddAttribute( "Append", SecurityElement.Escape( m_append.ToString() ) );
+                    esd.AddAttribute("Append", SecurityElement.Escape(m_append.ToString()));
                 }
                 if (this.m_pathDiscovery != null && !this.m_pathDiscovery.IsEmpty())
                 {
-                    esd.AddAttribute( "PathDiscovery", SecurityElement.Escape( m_pathDiscovery.ToString() ) );
+                    esd.AddAttribute("PathDiscovery", SecurityElement.Escape(m_pathDiscovery.ToString()));
                 }
                 if (this.m_viewAcl != null && !this.m_viewAcl.IsEmpty())
                 {
-                    esd.AddAttribute( "ViewAcl", SecurityElement.Escape( m_viewAcl.ToString() ) );
+                    esd.AddAttribute("ViewAcl", SecurityElement.Escape(m_viewAcl.ToString()));
                 }
                 if (this.m_changeAcl != null && !this.m_changeAcl.IsEmpty())
                 {
-                    esd.AddAttribute( "ChangeAcl", SecurityElement.Escape( m_changeAcl.ToString() ) );
+                    esd.AddAttribute("ChangeAcl", SecurityElement.Escape(m_changeAcl.ToString()));
                 }
 
             }
             else
             {
-                esd.AddAttribute( "Unrestricted", "true" );
+                esd.AddAttribute("Unrestricted", "true");
             }
             return esd;
         }
-        
+
         [System.Security.SecuritySafeCritical]  // auto-generated
         public override void FromXml(SecurityElement esd)
         {
-            CodeAccessPermission.ValidateElement( esd, this );
+            CodeAccessPermission.ValidateElement(esd, this);
             String et;
-            
+
             if (XMLUtil.IsUnrestricted(esd))
             {
                 m_unrestricted = true;
                 return;
             }
-    
-            
+
+
             m_unrestricted = false;
-            
-            et = esd.Attribute( "Read" );
+
+            et = esd.Attribute("Read");
             if (et != null)
             {
-                m_read = new FileIOAccess( et );
+                m_read = new FileIOAccess(et);
             }
             else
             {
                 m_read = null;
             }
-            
-            et = esd.Attribute( "Write" );
+
+            et = esd.Attribute("Write");
             if (et != null)
             {
-                m_write = new FileIOAccess( et );
+                m_write = new FileIOAccess(et);
             }
             else
             {
                 m_write = null;
             }
-    
-            et = esd.Attribute( "Append" );
+
+            et = esd.Attribute("Append");
             if (et != null)
             {
-                m_append = new FileIOAccess( et );
+                m_append = new FileIOAccess(et);
             }
             else
             {
                 m_append = null;
             }
 
-            et = esd.Attribute( "PathDiscovery" );
+            et = esd.Attribute("PathDiscovery");
             if (et != null)
             {
-                m_pathDiscovery = new FileIOAccess( et );
+                m_pathDiscovery = new FileIOAccess(et);
                 m_pathDiscovery.PathDiscovery = true;
             }
             else
@@ -838,20 +873,20 @@ namespace System.Security.Permissions {
                 m_pathDiscovery = null;
             }
 
-            et = esd.Attribute( "ViewAcl" );
+            et = esd.Attribute("ViewAcl");
             if (et != null)
             {
-                m_viewAcl = new FileIOAccess( et );
+                m_viewAcl = new FileIOAccess(et);
             }
             else
             {
                 m_viewAcl = null;
             }
 
-            et = esd.Attribute( "ChangeAcl" );
+            et = esd.Attribute("ChangeAcl");
             if (et != null)
             {
-                m_changeAcl = new FileIOAccess( et );
+                m_changeAcl = new FileIOAccess(et);
             }
             else
             {
@@ -875,60 +910,60 @@ namespace System.Security.Permissions {
         public override bool Equals(Object obj)
         {
             FileIOPermission perm = obj as FileIOPermission;
-            if(perm == null)
+            if (perm == null)
                 return false;
 
-            if(m_unrestricted && perm.m_unrestricted)
+            if (m_unrestricted && perm.m_unrestricted)
                 return true;
-            if(m_unrestricted != perm.m_unrestricted)
+            if (m_unrestricted != perm.m_unrestricted)
                 return false;
 
-            if(m_read == null)
+            if (m_read == null)
             {
-                if(perm.m_read != null && !perm.m_read.IsEmpty())
+                if (perm.m_read != null && !perm.m_read.IsEmpty())
                     return false;
             }
-            else if(!m_read.Equals(perm.m_read))
+            else if (!m_read.Equals(perm.m_read))
                 return false;
 
-            if(m_write == null)
+            if (m_write == null)
             {
-                if(perm.m_write != null && !perm.m_write.IsEmpty())
-                    return false; 
+                if (perm.m_write != null && !perm.m_write.IsEmpty())
+                    return false;
             }
-            else if(!m_write.Equals(perm.m_write))
+            else if (!m_write.Equals(perm.m_write))
                 return false;
 
-            if(m_append == null)
+            if (m_append == null)
             {
-                if(perm.m_append != null && !perm.m_append.IsEmpty())
-                    return false; 
+                if (perm.m_append != null && !perm.m_append.IsEmpty())
+                    return false;
             }
-            else if(!m_append.Equals(perm.m_append))
+            else if (!m_append.Equals(perm.m_append))
                 return false;
 
-            if(m_pathDiscovery == null)
+            if (m_pathDiscovery == null)
             {
-                if(perm.m_pathDiscovery != null && !perm.m_pathDiscovery.IsEmpty())
-                    return false; 
+                if (perm.m_pathDiscovery != null && !perm.m_pathDiscovery.IsEmpty())
+                    return false;
             }
-            else if(!m_pathDiscovery.Equals(perm.m_pathDiscovery))
+            else if (!m_pathDiscovery.Equals(perm.m_pathDiscovery))
                 return false;
 
-            if(m_viewAcl == null)
+            if (m_viewAcl == null)
             {
-                if(perm.m_viewAcl != null && !perm.m_viewAcl.IsEmpty())
-                    return false; 
+                if (perm.m_viewAcl != null && !perm.m_viewAcl.IsEmpty())
+                    return false;
             }
-            else if(!m_viewAcl.Equals(perm.m_viewAcl))
+            else if (!m_viewAcl.Equals(perm.m_viewAcl))
                 return false;
 
-            if(m_changeAcl == null)
+            if (m_changeAcl == null)
             {
-                if(perm.m_changeAcl != null && !perm.m_changeAcl.IsEmpty())
-                    return false; 
+                if (perm.m_changeAcl != null && !perm.m_changeAcl.IsEmpty())
+                    return false;
             }
-            else if(!m_changeAcl.Equals(perm.m_changeAcl))
+            else if (!m_changeAcl.Equals(perm.m_changeAcl))
                 return false;
 
             return true;
@@ -951,12 +986,8 @@ namespace System.Security.Permissions {
         /// IMPORTANT: This method should only be used after calling GetFullPath on the path to verify
         /// 
         /// </summary>
-        /// <param name="access"></param>
-        /// <param name="path"></param>
-        /// <param name="checkForDuplicates"></param>
-        /// <param name="needFullPath"></param>
         [System.Security.SecuritySafeCritical]
-        internal static void QuickDemand(FileIOPermissionAccess access, string fullPath, bool checkForDuplicates, bool needFullPath)
+        internal static void QuickDemand(FileIOPermissionAccess access, string fullPath, bool checkForDuplicates = false, bool needFullPath = true)
         {
             if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
             {
@@ -964,18 +995,109 @@ namespace System.Security.Permissions {
             }
             else
             {
-                //Emulate FileIOPermission checks
-                Path.CheckInvalidPathChars(fullPath, true);
+                EmulateFileIOPermissionChecks(fullPath);
+            }
+        }
+
+        /// <summary>
+        /// Call this method if you don't need a the FileIOPermission for anything other than calling Demand() once.
+        /// 
+        /// This method tries to verify full access before allocating a FileIOPermission object.
+        /// If full access is there, then we still have to emulate the checks that creating the 
+        /// FileIOPermission object would have performed.
+        /// 
+        /// IMPORTANT: This method should only be used after calling GetFullPath on the path to verify
+        /// 
+        /// </summary>
+        [System.Security.SecuritySafeCritical]
+        internal static void QuickDemand(FileIOPermissionAccess access, string[] fullPathList, bool checkForDuplicates = false, bool needFullPath = true)
+        {
+            if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+            {
+                new FileIOPermission(access, fullPathList, checkForDuplicates, needFullPath).Demand();
+            }
+            else
+            {
+                foreach (string fullPath in fullPathList)
+                {
+                    EmulateFileIOPermissionChecks(fullPath);
+                }
+            }
+        }
 
-                if (fullPath.Length > 2 && fullPath.IndexOf(':', 2) != -1)
+        [System.Security.SecuritySafeCritical]
+        internal static void QuickDemand(PermissionState state)
+        {
+            if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+            {
+                new FileIOPermission(state).Demand();
+            }
+        }
+
+#if FEATURE_MACL
+        [System.Security.SecuritySafeCritical]
+        internal static void QuickDemand(FileIOPermissionAccess access, AccessControlActions control, string fullPath, bool checkForDuplicates = false, bool needFullPath = true)
+        {
+            if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+            {
+                new FileIOPermission(access, control, new string[] { fullPath }, checkForDuplicates, needFullPath).Demand();
+            }
+            else
+            {
+                EmulateFileIOPermissionChecks(fullPath);
+            }
+        }
+
+        [System.Security.SecuritySafeCritical]
+        internal static void QuickDemand(FileIOPermissionAccess access, AccessControlActions control, string[] fullPathList, bool checkForDuplicates = true, bool needFullPath = true)
+        {
+            if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+            {
+                new FileIOPermission(access, control, fullPathList, checkForDuplicates, needFullPath).Demand();
+            }
+            else
+            {
+                foreach (string fullPath in fullPathList)
                 {
-                    throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported"));
+                    EmulateFileIOPermissionChecks(fullPath);
                 }
             }
         }
+#endif
+
+        /// <summary>
+        /// Perform the additional path checks that would normally happen when creating a FileIOPermission object.
+        /// </summary>
+        /// <param name="fullPath">A path that has already gone through GetFullPath or Normalize</param>
+        internal static void EmulateFileIOPermissionChecks(string fullPath)
+        {
+            // Callers should have already made checks for invalid path format via normalization. This method will only make the
+            // additional checks needed to throw the same exceptions that would normally throw when using FileIOPermission.
+            // These checks are done via CheckIllegalCharacters() and StringExpressionSet in AddPathList() above.
+            //
+            // We have to check the beginning as some paths may be passed in as path + @"\.", which will be normalized away.
+            BCLDebug.Assert(
+                fullPath.StartsWith(Path.NormalizePath(fullPath, fullCheck: false), StringComparison.OrdinalIgnoreCase),
+                string.Format("path isn't normalized: {0}", fullPath));
+
+            // Checking for colon / invalid characters on device paths blocks legitimate access to objects such as named pipes.
+            if (AppContextSwitches.UseLegacyPathHandling || !PathInternal.IsDevice(fullPath))
+            {
+                // GetFullPath already checks normal invalid path characters. We need to just check additional (wildcard) characters here.
+                // (By calling the standard helper we can allow extended paths \\?\ through when the support is enabled.)
+                if (PathInternal.HasWildCardCharacters(fullPath))
+                {
+                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
+                }
 
+                if (PathInternal.HasInvalidVolumeSeparator(fullPath))
+                {
+                    throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported"));
+                }
+            }
+        }
     }
-    
+
     [Serializable]
     internal sealed class FileIOAccess
     {
index 93cb2555874be2cc75fecc7495d40a9ebbab4379..e045de8e2539510de2f344c3ec9e55c863d022fc 100644 (file)
@@ -609,6 +609,8 @@ namespace System.Security.Principal
         // Public methods.
         //
         [SecuritySafeCritical]
+        [DynamicSecurityMethodAttribute()]
+        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
         public static void RunImpersonated(SafeAccessTokenHandle safeAccessTokenHandle, Action action)
         {
             if (action == null)
@@ -627,6 +629,8 @@ namespace System.Security.Principal
         }
 
         [SecuritySafeCritical]
+        [DynamicSecurityMethodAttribute()]
+        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
         public static T RunImpersonated<T>(SafeAccessTokenHandle safeAccessTokenHandle, Func<T> func)
         {
             if (func == null)
index 101d15ee58df3ef79f3ce1652dac39501d326d54..698f76f02e55e7dc627b20f63dcb9bdd4fc83efa 100644 (file)
@@ -219,33 +219,35 @@ namespace System.Security.Util {
                 throw new ArgumentNullException( "str" );
             }
             Contract.EndContractBlock();
+
             ArrayList retArrayList = new ArrayList();
             for (int index = 0; index < str.Length; ++index)
             {
                 if (str[index] == null)
                     throw new ArgumentNullException( "str" );
 
+                // Replace alternate directory separators
                 String oneString = StaticProcessWholeString( str[index] );
 
                 if (oneString != null && oneString.Length != 0)
                 {
-                    String temp = StaticProcessSingleString( oneString);
+                    // Trim leading and trailing spaces
+                    String temp = StaticProcessSingleString(oneString);
 
-                    int indexOfNull = temp.IndexOf( '\0' );
+                    int indexOfNull = temp.IndexOf('\0');
 
                     if (indexOfNull != -1)
-                        temp = temp.Substring( 0, indexOfNull );
+                        temp = temp.Substring(0, indexOfNull);
 
                     if (temp != null && temp.Length != 0)
                     {
-                        if (Path.IsRelative(temp))
+                        if (PathInternal.IsPartiallyQualified(temp))
                         {
-                            throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
+                            throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"));
                         }
 
                         temp = CanonicalizePath( temp, needFullPath );
 
-
                         retArrayList.Add( temp );
                     }
                 }
@@ -746,24 +748,14 @@ namespace System.Security.Util {
         [System.Security.SecurityCritical]  // auto-generated
         [ResourceExposure(ResourceScope.Machine)]
         [ResourceConsumption(ResourceScope.Machine)]
-        internal static String CanonicalizePath( String path, bool needFullPath )
+        internal static string CanonicalizePath(string path, bool needFullPath)
         {
-            if (path.IndexOf( '~' ) != -1)
-            {
-                string longPath = null;
-                GetLongPathName(path, JitHelpers.GetStringHandleOnStack(ref longPath));
-                path = (longPath != null) ? longPath : path;
-            }
-
-            if (path.IndexOf( ':', 2 ) != -1)
-                throw new NotSupportedException( Environment.GetResourceString( "Argument_PathFormatNotSupported" ) );
-
             if (needFullPath)
             {
-                String newPath = System.IO.Path.GetFullPathInternal( path );
-                if (path.EndsWith( m_directorySeparator + ".", StringComparison.Ordinal ))
+                string newPath = Path.GetFullPathInternal(path);
+                if (path.EndsWith(m_directorySeparator + ".", StringComparison.Ordinal))
                 {
-                    if (newPath.EndsWith( m_directorySeparator ))
+                    if (newPath.EndsWith(m_directorySeparator))
                     {
                         newPath += ".";
                     }
@@ -771,11 +763,23 @@ namespace System.Security.Util {
                     {
                         newPath += m_directorySeparator + ".";
                     }
-                }                
-                return newPath;
+                }
+                path = newPath;
             }
-            else
-                return path;
+            else if (path.IndexOf('~') != -1)
+            {
+                // GetFullPathInternal() will expand 8.3 file names
+                string longPath = null;
+                GetLongPathName(path, JitHelpers.GetStringHandleOnStack(ref longPath));
+                path = (longPath != null) ? longPath : path;
+            }
+
+            // This blocks usage of alternate data streams and some extended syntax paths (\\?\C:\). Checking after
+            // normalization allows valid paths such as " C:\" to be considered ok (as it will become "C:\").
+            if (path.IndexOf(':', 2) != -1)
+                throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported"));
+
+            return path;
         }
     }
 }
index b009ff0a8ecf6fc0016ce8cd322fc18eb62e9a39..c629fb4f695051b0c9aa39fba9b469fcdc897481 100644 (file)
@@ -354,13 +354,24 @@ namespace System.Security.Util {
         // 3. Throws a PathTooLongException if the length of the resulting URL is >= MAX_PATH.
         //    This is done to prevent security issues due to canonicalization truncations.
         // Remove this method when the Path class supports "\\?\"
-        internal static String PreProcessForExtendedPathRemoval(String url, bool isFileUrl)
+        internal static string PreProcessForExtendedPathRemoval(string url, bool isFileUrl)
         {
-            bool uncShare = false;
-            return PreProcessForExtendedPathRemoval(url, isFileUrl, ref uncShare);
+            return PreProcessForExtendedPathRemoval(checkPathLength: true, url: url, isFileUrl: isFileUrl);
         }
 
-        private static String PreProcessForExtendedPathRemoval(String url, bool isFileUrl, ref bool isUncShare)
+        internal static string PreProcessForExtendedPathRemoval(bool checkPathLength, string url, bool isFileUrl)
+        {
+            bool isUncShare = false;
+            return PreProcessForExtendedPathRemoval(checkPathLength: checkPathLength, url: url, isFileUrl: isFileUrl, isUncShare: ref isUncShare);
+        }
+
+        // Keeping this signature to avoid reflection breaks
+        private static string PreProcessForExtendedPathRemoval(string url, bool isFileUrl, ref bool isUncShare)
+        {
+            return PreProcessForExtendedPathRemoval(checkPathLength: true, url: url, isFileUrl: isFileUrl, isUncShare: ref isUncShare);
+        }
+
+        private static string PreProcessForExtendedPathRemoval(bool checkPathLength, string url, bool isFileUrl, ref bool isUncShare)
         {
             // This is the modified URL that we will return
             StringBuilder modifiedUrl = new StringBuilder(url);
@@ -434,15 +445,24 @@ namespace System.Security.Util {
             }
 
             // ITEM 3 - If the path is greater than or equal (due to terminating NULL in windows) MAX_PATH, we throw.
-            if (modifiedUrl.Length >= Path.MAX_PATH)
+            if (checkPathLength)
             {
-                throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+                // This needs to be a separate method to avoid hitting the static constructor on AppContextSwitches
+                CheckPathTooLong(modifiedUrl);
             }
 
             // Create the result string from the StringBuilder
             return modifiedUrl.ToString();
         }
 
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void CheckPathTooLong(StringBuilder path)
+        {
+            if (path.Length >= (AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : PathInternal.MaxLongPath))
+            {
+                throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+            }
+        }
 
         // Do any misc massaging of data in the URL
         private String PreProcessURL(String url, bool isFileURL)
index 357bfe6c6ae7620f6e8d920db4bd92276e648182..46c377bdebae60fc7e70105d0cbd79f6cd76186b 100644 (file)
@@ -1968,7 +1968,7 @@ namespace System.Text {
 
             VerifyClassInvariant();
 
-            if ((minBlockCharCount + Length) > m_MaxCapacity)
+            if (minBlockCharCount + Length < minBlockCharCount || (minBlockCharCount + Length) > m_MaxCapacity)
                 throw new ArgumentOutOfRangeException("requiredLength", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
 
             // Compute the length of the new block we need 
@@ -2028,7 +2028,8 @@ namespace System.Text {
             VerifyClassInvariant();
             Contract.Assert(count > 0, "Count must be strictly positive");
             Contract.Assert(index >= 0, "Index can't be negative");
-            if (count + Length > m_MaxCapacity)
+
+            if (count + Length < count || count + Length > m_MaxCapacity)
                 throw new ArgumentOutOfRangeException("requiredLength", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
 
             chunk = this;
index 1e3f9293f7c31efdabd588b569ba8cd587752795..6ee970a08efe8a6db1ba7d82b85a2d685c96bd2b 100644 (file)
@@ -3630,7 +3630,14 @@ namespace System.Threading.Tasks
                 ITaskCompletionAction singleTaskCompletionAction = continuationObject as ITaskCompletionAction;
                 if (singleTaskCompletionAction != null)
                 {
-                    singleTaskCompletionAction.Invoke(this);
+                    if (bCanInlineContinuations)
+                    {
+                        singleTaskCompletionAction.Invoke(this);
+                    }
+                    else
+                    {
+                        ThreadPool.UnsafeQueueCustomWorkItem(new CompletionActionInvoker(singleTaskCompletionAction, this), forceGlobal: false);
+                    }
                     LogFinishCompletionNotification();
                     return;
                 }
@@ -3711,7 +3718,15 @@ namespace System.Threading.Tasks
                         {
                             Contract.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction");
                             var action = (ITaskCompletionAction)currentContinuation;
-                            action.Invoke(this);
+
+                            if (bCanInlineContinuations)
+                            {
+                                action.Invoke(this);
+                            }
+                            else
+                            {
+                                ThreadPool.UnsafeQueueCustomWorkItem(new CompletionActionInvoker(action, this), forceGlobal: false);
+                            }
                         }
                     }
                 }
@@ -6673,6 +6688,30 @@ namespace System.Threading.Tasks
         }
     }
 
+    internal sealed class CompletionActionInvoker : IThreadPoolWorkItem
+    {
+        private readonly ITaskCompletionAction m_action;
+        private readonly Task m_completingTask;
+
+        internal CompletionActionInvoker(ITaskCompletionAction action, Task completingTask)
+        {
+            m_action = action;
+            m_completingTask = completingTask;
+        }
+        
+        [SecurityCritical]
+        public void ExecuteWorkItem()
+        {
+            m_action.Invoke(m_completingTask);
+        }
+        
+        [SecurityCritical]
+        public void MarkAborted(ThreadAbortException tae)
+        {
+            /* NOP */
+        }
+    } 
+
     // Proxy class for better debugging experience
     internal class SystemThreadingTasks_TaskDebugView
     {
index 004d29f8bd25dec87cc69901bd57b869d37cf9b5..85dff2b3c84fcb71651275ea08fb316c379f9d64 100644 (file)
@@ -20,6 +20,7 @@ using System.Security.Cryptography;
 using System.Security.Permissions;
 using Mono.Security.Cryptography;
 using Mono.CompilerServices.SymbolWriter;
+using System.Linq;
 
 #if STATIC
 using IKVM.Reflection;
@@ -43,6 +44,20 @@ namespace Mono.CSharp
                byte[] GetPublicKeyToken ();
                bool IsFriendAssemblyTo (IAssemblyDefinition assembly);
        }
+
+       public class AssemblyReferenceErrorInfo
+       {
+               public AssemblyReferenceErrorInfo (AssemblyName dependencyName, string location, string message)
+               {
+                       this.DependencyName = dependencyName;
+                       this.RequestingAssemblyLocation = location;
+                       this.Message = message;
+               }
+
+               public AssemblyName DependencyName { get; private set; }
+               public string RequestingAssemblyLocation { get; private set; }
+               public string Message { get; private set; }
+       }
                 
        public abstract class AssemblyDefinition : IAssemblyDefinition
        {
@@ -416,7 +431,8 @@ namespace Mono.CSharp
                //
                void CheckReferencesPublicToken ()
                {
-                       foreach (var an in builder_extra.GetReferencedAssemblies ()) {
+                       var references = builder_extra.GetReferencedAssemblies ();
+                       foreach (var an in references) {
                                if (public_key != null && an.GetPublicKey ().Length == 0) {
                                        Report.Error (1577, "Referenced assembly `{0}' does not have a strong name",
                                                an.FullName);
@@ -432,11 +448,17 @@ namespace Mono.CSharp
                                if (ia == null)
                                        continue;
 
-                               var references = GetNotUnifiedReferences (an);
-                               if (references != null) {
-                                       foreach (var r in references) {
-                                               Report.SymbolRelatedToPreviousError ( r[0]);
-                                               Report.Error (1705, r [1]);
+                               var an_references = GetNotUnifiedReferences (an);
+                               if (an_references != null) {
+                                       foreach (var r in an_references) {
+                                               //
+                                               // Secondary check when assembly references is resolved but not used. For example
+                                               // due to type-forwarding
+                                               //
+                                               if (references.Any (l => l.Name == r.DependencyName.Name)) {
+                                                       Report.SymbolRelatedToPreviousError (r.RequestingAssemblyLocation);
+                                                       Report.Error (1705, r.Message);
+                                               }
                                        }
                                }
 
@@ -570,7 +592,7 @@ namespace Mono.CSharp
                        return public_key_token;
                }
 
-               protected virtual List<string[]> GetNotUnifiedReferences (AssemblyName assemblyName)
+               protected virtual List<AssemblyReferenceErrorInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
                {
                        return null;
                }
index 75a02034f9cf9cda8bef266f139325a055c15546..f4b9930f3999e8c3395d53a4319744d1130492c0 100644 (file)
@@ -220,7 +220,7 @@ namespace Mono.CSharp
                        return Builder.__AddModule (moduleFile);
                }
 
-               protected override List<string[]> GetNotUnifiedReferences (AssemblyName assemblyName)
+               protected override List<AssemblyReferenceErrorInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
                {
                        return loader.GetNotUnifiedReferences (assemblyName);
                }
@@ -238,7 +238,7 @@ namespace Mono.CSharp
                Assembly corlib;
                readonly List<Tuple<AssemblyName, string, Assembly>> loaded_names;
                static readonly Dictionary<string, string[]> sdk_directory;
-               Dictionary<AssemblyName, List<string[]>> resolved_version_mismatches;
+               Dictionary<AssemblyName, List<AssemblyReferenceErrorInfo>> resolved_version_mismatches;
                static readonly TypeName objectTypeName = new TypeName ("System", "Object");
 
                static StaticLoader ()
@@ -359,25 +359,24 @@ namespace Mono.CSharp
                                if (version_mismatch is AssemblyBuilder)
                                        return version_mismatch;
 
-                               var v1 = new AssemblyName (refname).Version;
+                               var ref_an = new AssemblyName (refname);
+                               var v1 = ref_an.Version;
                                var v2 = version_mismatch.GetName ().Version;
 
                                if (v1 > v2) {
                                        if (resolved_version_mismatches == null)
-                                               resolved_version_mismatches = new Dictionary<AssemblyName, List<string[]>> ();
+                                               resolved_version_mismatches = new Dictionary<AssemblyName, List<AssemblyReferenceErrorInfo>> ();
 
                                        var an = args.RequestingAssembly.GetName ();
-                                       List<string[]> names;
+                                       List<AssemblyReferenceErrorInfo> names;
                                        if (!resolved_version_mismatches.TryGetValue (an, out names)) {
-                                               names = new List<string[]> ();
+                                               names = new List<AssemblyReferenceErrorInfo> ();
                                                resolved_version_mismatches.Add (an, names);
                                        }
 
-                                       names.Add (new[] {
-                                               args.RequestingAssembly.Location,
+                                       names.Add (new AssemblyReferenceErrorInfo (ref_an, args.RequestingAssembly.Location,
                                                string.Format ("Assembly `{0}' depends on `{1}' which has a higher version number than referenced assembly `{2}'",
-                                                       args.RequestingAssembly.FullName, refname, version_mismatch.GetName ().FullName)
-                                       });
+                                                          args.RequestingAssembly.FullName, refname, version_mismatch.GetName ().FullName)));
 
                                        return version_mismatch;
                                }
@@ -434,9 +433,9 @@ namespace Mono.CSharp
                        return default_references.ToArray ();
                }
 
-               public List<string[]> GetNotUnifiedReferences (AssemblyName assemblyName)
+               public List<AssemblyReferenceErrorInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
                {
-                       List<string[]> list = null;
+                       List<AssemblyReferenceErrorInfo> list = null;
                        if (resolved_version_mismatches != null)
                                resolved_version_mismatches.TryGetValue (assemblyName, out list);
 
index 10674f5cd9ec50902bc0db9d25355599b17fa65d..a149e2eb536cb3f61714de3073ead029a3aa9405 100644 (file)
@@ -98,4 +98,8 @@ csproj-local:
 setup:
        $(CSCOMPILE) -t:library dlls/test-679-2/test-679-lib-2.cs
        $(CSCOMPILE) -t:library dlls/test-679-1/test-679-lib.cs -r:dlls/test-679-2/test-679-lib-2.dll
+       $(CSCOMPILE) -t:library dlls/test-939-common.cs -keyfile:key.snk -publicsign
+       $(CSCOMPILE) -t:library dlls/test-939-1/test-939-lib.cs -keyfile:key.snk -publicsign
+       $(CSCOMPILE) -t:library dlls/test-939-1/test-939-ref.cs -r:dlls/test-939-1/test-939-lib.dll -keyfile:key.snk -publicsign
+       $(CSCOMPILE) -t:library dlls/test-939-2/test-939-lib.cs -r:dlls/test-939-common.dll -keyfile:key.snk -publicsign
        $(ILASM) -dll dlls/test-883.il
diff --git a/mcs/tests/dlls/test-939-1/test-939-lib.cs b/mcs/tests/dlls/test-939-1/test-939-lib.cs
new file mode 100644 (file)
index 0000000..1351652
--- /dev/null
@@ -0,0 +1,9 @@
+[assembly:System.Reflection.AssemblyVersionAttribute ("2.1.0.0")]
+
+public class Common
+{
+       public static void Foo ()
+       {
+
+       }
+}
diff --git a/mcs/tests/dlls/test-939-1/test-939-ref.cs b/mcs/tests/dlls/test-939-1/test-939-ref.cs
new file mode 100644 (file)
index 0000000..580d407
--- /dev/null
@@ -0,0 +1,10 @@
+[assembly:System.Reflection.AssemblyVersionAttribute ("4.0.0.0")]
+
+public class A : Common
+{
+}
+
+public class B
+{
+       
+}
diff --git a/mcs/tests/dlls/test-939-2/test-939-lib.cs b/mcs/tests/dlls/test-939-2/test-939-lib.cs
new file mode 100644 (file)
index 0000000..b660068
--- /dev/null
@@ -0,0 +1,5 @@
+using System.Runtime.CompilerServices;
+
+[assembly:System.Reflection.AssemblyVersionAttribute ("2.0.0.0")]
+
+[assembly:TypeForwardedTo (typeof (Common))]
diff --git a/mcs/tests/dlls/test-939-common.cs b/mcs/tests/dlls/test-939-common.cs
new file mode 100644 (file)
index 0000000..a6420bb
--- /dev/null
@@ -0,0 +1,9 @@
+[assembly:System.Reflection.AssemblyVersionAttribute ("1.0.0.0")]
+
+public class Common
+{
+       public static void Foo ()
+       {
+
+       }
+}
diff --git a/mcs/tests/test-939.cs b/mcs/tests/test-939.cs
new file mode 100644 (file)
index 0000000..7d83ddf
--- /dev/null
@@ -0,0 +1,14 @@
+// Compiler options: -r:dlls/test-939-1/test-939-ref.dll -r:dlls/test-939-2/test-939-lib.dll -r:dlls/test-939-common.dll
+
+class X
+{
+       public static void Main ()
+       {
+       }
+
+       static void RealTest ()
+       {
+               A.Foo ();
+               new B ();
+       }
+}
\ No newline at end of file
index cf1b181359111ffbc14a818e673130866fa39d1d..3dd524c4960c0d054ec1f4926142cfc454ee98c6 100644 (file)
@@ -5,6 +5,7 @@ using System.Threading;
 class X
 {
        static ManualResetEvent dispose = new ManualResetEvent (false);
+       static ManualResetEvent wait = new ManualResetEvent (false);
 
        static IEnumerable GetIt2 ()
        {
@@ -15,7 +16,7 @@ class X
        static int Delay ()
        {
                dispose.Set ();
-               Thread.Sleep (10);
+               wait.WaitOne ();
                return 1;
        }
 
@@ -25,6 +26,7 @@ class X
                ThreadPool.QueueUserWorkItem (l => {
                        dispose.WaitOne ();
                        ((IDisposable) e).Dispose ();
+                       wait.Set ();
                });
 
                if (!e.MoveNext ())
index c705efa9a031fbfcd360998fccab5c8d635e52ed..33a932710a489b7be51602237e4abd76cb5ac242 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-939.cs">
+    <type name="X">
+      <method name="Void Main()" attrs="150">
+        <size>2</size>
+      </method>
+      <method name="Void RealTest()" attrs="145">
+        <size>13</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-94.cs">
     <type name="Base">
       <method name="Int32 IVehicle.Start()" attrs="481">
   <test name="test-iter-23.cs">
     <type name="X">
       <method name="Int32 Delay()" attrs="145">
-        <size>28</size>
+        <size>32</size>
       </method>
       <method name="Int32 Main()" attrs="150">
         <size>141</size>
         <size>7</size>
       </method>
       <method name="Void .cctor()" attrs="6289">
-        <size>12</size>
+        <size>23</size>
       </method>
     </type>
     <type name="X+&lt;GetIt2&gt;c__Iterator0">
     </type>
     <type name="X+&lt;Main&gt;c__AnonStorey1">
       <method name="Void &lt;&gt;m__0(System.Object)" attrs="131">
-        <size>29</size>
+        <size>40</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
index aa235d31fbda17f9698cffa9442ca7a350d11c53..f7074361022d4314aa934b4e5954245d5adacf89 100644 (file)
@@ -160,7 +160,7 @@ check-monodocer-addNonGeneric: $(PROGRAM)
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-addNonGeneric-v2.dll
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-addNonGeneric-v2.dll
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-addNonGeneric-v2.dll
-       diff --exclude=.svn -rup Test/en.expected-addNonGeneric Test/en.actual
+       diff -rup Test/en.expected-addNonGeneric Test/en.actual
 
 check-monodocer-dropns-classic: $(PROGRAM)
        # tests the simplest --dropns case, a single class where the root namespace was dropped.
@@ -168,7 +168,7 @@ check-monodocer-dropns-classic: $(PROGRAM)
        $(MAKE) Test/DocTest-DropNS-classic.dll
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic.dll --api-style=classic
        $(MAKE) update-monodocer-dropns-unified
-       diff --exclude=.svn -rup Test/en.expected-dropns-classic-v1 Test/en.actual
+       diff -rup Test/en.expected-dropns-classic-v1 Test/en.actual
 
 check-monodocer-dropns-multi: $(PROGRAM)
        -rm -Rf Test/en.actual
@@ -185,7 +185,7 @@ check-monodocer-dropns-multi: $(PROGRAM)
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic 
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework 
        
-       diff --exclude=.svn -rup Test/en.expected-dropns-multi Test/en.actual
+       diff -rup Test/en.expected-dropns-multi Test/en.actual
 
 
 check-monodocer-dropns-multi-withexisting: $(PROGRAM)
@@ -203,7 +203,7 @@ check-monodocer-dropns-multi-withexisting: $(PROGRAM)
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic 
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework 
        
-       diff --exclude=.svn -rup Test/en.expected-dropns-multi-withexisting Test/en.actual
+       diff -rup Test/en.expected-dropns-multi-withexisting Test/en.actual
 
 check-monodocer-dropns-delete: $(PROGRAM)
        -rm -Rf Test/en.actual
@@ -217,7 +217,7 @@ check-monodocer-dropns-delete: $(PROGRAM)
        $(MONO) $(PROGRAM) update --delete --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic-deletetest.dll --api-style=classic
        $(MAKE) Test/DocTest-DropNS-unified-deletetest-V2.dll
        $(MONO) $(PROGRAM) update --delete --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified-deletetest.dll --api-style=unified --dropns Test/DocTest-DropNS-unified-deletetest.dll=MyFramework
-       diff --exclude=.dvn -rup Test/en.expected-dropns-delete Test/en.actual
+       diff -rup Test/en.expected-dropns-delete Test/en.actual
 
 check-monodocer-dropns-classic-withsecondary: $(PROGRAM)
        # tests case where a secondary assembly is included with a --dropns parameter
@@ -226,7 +226,7 @@ check-monodocer-dropns-classic-withsecondary: $(PROGRAM)
        $(MAKE) Test/DocTest-DropNS-classic-secondary.dll
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic.dll Test/DocTest-DropNS-classic-secondary.dll --api-style=classic
        $(MAKE) update-monodocer-dropns-unified-withsecondary
-       diff --exclude=.svn -rup Test/en.expected-dropns-classic-withsecondary Test/en.actual
+       diff -rup Test/en.expected-dropns-classic-withsecondary Test/en.actual
 
 update-monodocer-dropns-unified: $(PROGRAM)
        $(MAKE) Test/DocTest-DropNS-unified.dll
@@ -245,13 +245,13 @@ check-monodocer-internal-interface: $(PROGRAM)
        -rm -Rf Test/en.actual
        $(MAKE) Test/DocTest-InternalInterface.dll
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-InternalInterface.dll
-       diff --exclude=.svn -rup Test/en.expected-internal-interface Test/en.actual
+       diff -rup Test/en.expected-internal-interface Test/en.actual
 
 check-monodocer-enumerations: $(PROGRAM)
        -rm -Rf Test/en.actual
        $(MAKE) Test/DocTest-enumerations.dll
        $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-enumerations.dll
-       diff --exclude=.svn -rup Test/en.expected-enumerations Test/en.actual
+       diff -rup Test/en.expected-enumerations Test/en.actual
 
 check-monodocer-update: $(PROGRAM)
        find Test/en.expected -name \*.xml -exec rm "{}" \;
@@ -262,9 +262,9 @@ check-monodocer: $(PROGRAM)
        -rm -Rf Test/en.actual
        $(MAKE) Test/DocTest.dll-v1
        $(MONO) $(PROGRAM) update --debug --exceptions=all -o Test/en.actual Test/DocTest.dll
-       diff --exclude=.svn -rup Test/en.expected Test/en.actual
+       diff -rup Test/en.expected Test/en.actual
        $(MONO) $(PROGRAM) update --debug --exceptions=all -o Test/en.actual Test/DocTest.dll 
-       diff --exclude=.svn -rup Test/en.expected Test/en.actual
+       diff -rup Test/en.expected Test/en.actual
 
 check-monodocer-since-update: $(PROGRAM)
        find Test/en.expected.since -name \*.xml -exec rm "{}" \;
@@ -281,7 +281,7 @@ check-monodocer-since: $(PROGRAM)
        $(MAKE) Test/DocTest.dll-v2
        $(MONO) $(PROGRAM) --debug update --exceptions=all --since="Version 2.0" \
                -o Test/en.actual Test/DocTest.dll 
-       diff --exclude=.svn -rup Test/en.expected.since Test/en.actual
+       diff -rup Test/en.expected.since Test/en.actual
 
 check-monodocer-delete-update: $(PROGRAM)
        find Test/en.expected.delete -type f -exec rm "{}" \;
@@ -301,7 +301,7 @@ check-monodocer-delete: $(PROGRAM)
        $(MONO) $(PROGRAM) --debug update --exceptions=all -o Test/en.actual Test/DocTest.dll
        $(MAKE) Test/DocTest.dll-v1
        $(MONO) $(PROGRAM) --debug update -fno-assembly-versions --delete --exceptions=all -o Test/en.actual Test/DocTest.dll
-       diff --exclude=.svn -rup Test/en.expected.delete Test/en.actual
+       diff -rup Test/en.expected.delete Test/en.actual
 
 check-monodocer-importslashdoc-update: $(PROGRAM)
        find Test/en.expected.importslashdoc -name \*.xml -exec rm "{}" \;
@@ -314,7 +314,7 @@ check-monodocer-importslashdoc: $(PROGRAM)
        $(MAKE) Test/DocTest.dll-v1 TEST_CSCFLAGS=-doc:Test/DocTest.xml
        $(MONO) $(PROGRAM) --debug update --exceptions=all -i Test/DocTest.xml \
                -o Test/en.actual Test/DocTest.dll 
-       diff --exclude=.svn -rup Test/en.expected.importslashdoc Test/en.actual
+       diff -rup Test/en.expected.importslashdoc Test/en.actual
 
 check-monodocer-importecmadoc-update: $(PROGRAM)
        find Test/en.expected.importecmadoc -name \*.xml -exec rm "{}" \;
@@ -331,7 +331,7 @@ check-monodocer-importecmadoc: $(PROGRAM)
                '--type=System.Action`1' --type=System.AsyncCallback \
                --type=System.Environment --type=System.Array \
                -o Test/en.actual Test/DocTest.dll 
-       diff --exclude=.svn -rup Test/en.expected.importecmadoc Test/en.actual
+       diff -rup Test/en.expected.importecmadoc Test/en.actual
 
 check-mdoc-export-html-update: $(PROGRAM)
        find Test/html.expected -name \*.html -exec rm "{}" \;
@@ -342,7 +342,7 @@ check-mdoc-export-html: check-monodocer $(PROGRAM)
        rm -Rf Test/html.actual
        $(MONO) $(PROGRAM) export-html -o Test/html.actual \
                Test/en.expected.importslashdoc
-       diff --exclude=.svn -rup Test/html.expected Test/html.actual
+       diff -rup Test/html.expected Test/html.actual
 
 check-mdoc-export-html-with-version: $(PROGRAM)
        rm -Rf Test/html.actual.v0 Test/html.actual.since-with-v0 .v0.txt .v2.txt
@@ -357,7 +357,7 @@ check-mdoc-export-html-with-version: $(PROGRAM)
 check-md-html-dir: $(PROGRAM)
        rm -Rf Test/html.actual
        $(MONO) $(PROGRAM) export-html -dest:Test/html.actual $(DIR) 
-       diff --exclude=.svn -rup Test/html.expected Test/html.actual
+       diff -rup Test/html.expected Test/html.actual
 
 check-mdoc-export-msxdoc-update:
        $(MONO) $(PROGRAM) export-msxdoc -o - Test/en.expected.importslashdoc \
index 2382d37d43d3d04657bb2bcc31759a12bbca39c4..86a7132bbcbbda9dba00aa6085418e760a62a817 100755 (executable)
@@ -256,27 +256,16 @@ class MakeBundle {
 
                }
 
-               if (!quiet) {
-                       Console.WriteLine (os_message);
-                       Console.WriteLine ("Sources: {0} Auto-dependencies: {1}", sources.Count, autodeps);
-               }
-               if (sources.Count == 0 || output == null) {
-                       Help ();
-                       Environment.Exit (1);
-               }
-
-               List<string> assemblies = LoadAssemblies (sources);
-               List<string> files = new List<string> ();
-               foreach (string file in assemblies)
-                       if (!QueueAssembly (files, file))
-                               return 1;
-
                if (fetch_target != null){
                        var truntime = Path.Combine (targets_dir, fetch_target, "mono");
                        Directory.CreateDirectory (Path.GetDirectoryName (truntime));
                        var wc = new WebClient ();
                        var uri = new Uri ($"{target_server}{fetch_target}");
                        try {
+                               if (!quiet){
+                                       Console.WriteLine ($"Downloading runtime {uri} to {truntime}");
+                               }
+                               
                                wc.DownloadFile (uri, truntime);
                        } catch {
                                Console.Error.WriteLine ($"Failure to download the specified runtime from {uri}");
@@ -286,27 +275,47 @@ class MakeBundle {
                        return 0;
                }
                
+               if (!quiet) {
+                       Console.WriteLine (os_message);
+                       Console.WriteLine ("Sources: {0} Auto-dependencies: {1}", sources.Count, autodeps);
+               }
+
+               if (sources.Count == 0 || output == null) {
+                       Help ();
+                       Environment.Exit (1);
+               }
+
+               List<string> assemblies = LoadAssemblies (sources);
+               List<string> files = new List<string> ();
+               foreach (string file in assemblies)
+                       if (!QueueAssembly (files, file))
+                               return 1;
+
                if (custom_mode)
                        GenerateBundles (files);
                else {
                        if (cross_target == "default")
                                runtime = null;
                        else {
-                               string truntime;
-                               if (runtime != null)
-                                       truntime = runtime;
-                               else {
+                               if (runtime == null){
                                        if (cross_target == null){
                                                Console.Error.WriteLine ("you should specify either a --runtime or a --cross compilation target");
                                                Environment.Exit (1);
                                        }
-                                       truntime = Path.Combine (targets_dir, cross_target, "mono");
-                               }
-                               if (!File.Exists (truntime)){
-                                       Console.Error.WriteLine ($"The runtime for the {cross_target} does not exist, use --fetch-target {cross_target} to download first");
-                                       return 1;
+                                       runtime = Path.Combine (targets_dir, cross_target, "mono");
+                                       if (!File.Exists (runtime)){
+                                               Console.Error.WriteLine ($"The runtime for the {cross_target} does not exist, use --fetch-target {cross_target} to download first");
+                                               return 1;
+                                       }
+                               } else {
+                                       if (!File.Exists (runtime)){
+                                               Console.Error.WriteLine ($"The Mono runtime specified with --runtime does not exist");
+                                               return 1;
+                                       }
                                }
-                       }                               
+                               
+                               Console.WriteLine ("Using runtime {0}", runtime);
+                       }
                        GeneratePackage (files);
                }
                
index adbd862eb923bcba7c67f3a792b30862d6c78234..f09ab497ee01a17e91dea151682ffb5d7121cc50 100644 (file)
@@ -66,7 +66,13 @@ namespace Xamarin.ApiDiff {
                {
                        SourceAssembly = source.GetAttribute ("name");
                        TargetAssembly = target.GetAttribute ("name");
-                       // TODO: version
+
+                       var sb = source.GetAttribute ("version");
+                       var tb = target.GetAttribute ("version");
+                       if (sb != tb) {
+                               Output.WriteLine ("<h4>Assembly Version Changed: {0} vs {1}</h4>", tb, sb);
+                       }
+
                        // ? custom attributes ?
                        comparer.Compare (source, target);
                }
index ee6d7a650513dbf254d4b81be37cec80dcdeb801..79c8537551f7f469cdb1b8f1505b1d78c06d8fb4 100644 (file)
@@ -73,9 +73,12 @@ namespace NUnitLite
         //             Example usage: -exclude:category1,category2 this command can be used
         //             in combination with the -include option also note that exclude takes priority
         //             over all includes
-        public static void Main(string[] args)
+        public static int Main(string[] args)
         {
-            new TextUI().Execute(args);
+            var runner = new TextUI();
+            runner.Execute(args);
+            
+            return (runner.Failure ? 1 : 0);
         }
     }
 }
index 889c19ece4f786221a020fc365cebe41983b7734..bedd740079bfdc160e07c76ae65b67134f7af777 100644 (file)
@@ -51,6 +51,15 @@ register_icall (gpointer func, const char *name, const char *sigstr, gboolean sa
        mono_register_jit_icall (func, name, sig, save);
 }
 
+gpointer
+mono_string_to_bstr(MonoString* ptr)
+{
+       if (!ptr)
+               return NULL;
+
+       return mono_ptr_to_bstr(mono_string_chars(ptr), mono_string_length(ptr));
+}
+
 #ifndef DISABLE_COM
 
 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
@@ -2742,37 +2751,37 @@ init_com_provider_ms (void)
 }
 
 gpointer
-mono_string_to_bstr (MonoString *string_obj)
+mono_ptr_to_bstr(gpointer ptr, int slen)
 {
-       if (!string_obj)
+       if (!ptr)
                return NULL;
 #ifdef HOST_WIN32
-       return SysAllocStringLen (mono_string_chars (string_obj), mono_string_length (string_obj));
+       return SysAllocStringLen (ptr, slen);
 #else
        if (com_provider == MONO_COM_DEFAULT) {
-               int slen = mono_string_length (string_obj);
                /* allocate len + 1 utf16 characters plus 4 byte integer for length*/
-               char *ret = (char *)g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32));
+               char *ret = (char *)g_malloc((slen + 1) * sizeof(gunichar2) + sizeof(guint32));
                if (ret == NULL)
                        return NULL;
-               memcpy (ret + sizeof(guint32), mono_string_chars (string_obj), slen * sizeof(gunichar2));
-               * ((guint32 *) ret) = slen * sizeof(gunichar2);
-               ret [4 + slen * sizeof(gunichar2)] = 0;
-               ret [5 + slen * sizeof(gunichar2)] = 0;
+               memcpy(ret + sizeof(guint32), ptr, slen * sizeof(gunichar2));
+               *((guint32 *)ret) = slen * sizeof(gunichar2);
+               ret[4 + slen * sizeof(gunichar2)] = 0;
+               ret[5 + slen * sizeof(gunichar2)] = 0;
 
                return ret + 4;
-       } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
+       }
+       else if (com_provider == MONO_COM_MS && init_com_provider_ms()) {
                gpointer ret = NULL;
                gunichar* str = NULL;
-               guint32 len;
-               len = mono_string_length (string_obj);
-               str = g_utf16_to_ucs4 (mono_string_chars (string_obj), len,
+               guint32 len = slen;
+               str = g_utf16_to_ucs4(ptr, len,
                        NULL, NULL, NULL);
-               ret = sys_alloc_string_len_ms (str, len);
+               ret = sys_alloc_string_len_ms(str, len);
                g_free(str);
                return ret;
-       } else {
-               g_assert_not_reached ();
+       }
+       else {
+               g_assert_not_reached();
        }
 #endif
 }
@@ -3411,20 +3420,19 @@ cominterop_release_all_rcws (void)
 }
 
 gpointer
-mono_string_to_bstr (MonoString *string_obj)
+mono_ptr_to_bstr (gpointer ptr, int slen)
 {
-       if (!string_obj)
+       if (!ptr)
                return NULL;
 #ifdef HOST_WIN32
-       return SysAllocStringLen (mono_string_chars (string_obj), mono_string_length (string_obj));
+       return SysAllocStringLen (ptr, slen);
 #else
        {
-               int slen = mono_string_length (string_obj);
                /* allocate len + 1 utf16 characters plus 4 byte integer for length*/
                char *ret = g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32));
                if (ret == NULL)
                        return NULL;
-               memcpy (ret + sizeof(guint32), mono_string_chars (string_obj), slen * sizeof(gunichar2));
+               memcpy (ret + sizeof(guint32), ptr, slen * sizeof(gunichar2));
                * ((guint32 *) ret) = slen * sizeof(gunichar2);
                ret [4 + slen * sizeof(gunichar2)] = 0;
                ret [5 + slen * sizeof(gunichar2)] = 0;
@@ -3524,6 +3532,12 @@ ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString* ptr)
        return mono_string_to_bstr(ptr);
 }
 
+gpointer
+ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (MonoArray* ptr, int len)
+{
+       return mono_ptr_to_bstr (ptr->vector, len);
+}
+
 void
 ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (gpointer ptr)
 {
index aa4c324372e7aa9c9f0a2e52e9f1394c8a7aff65..f5e8d29ba3088aa08a9acf3f2e4686ab5e9965db 100644 (file)
@@ -189,6 +189,11 @@ void mono_handle_verify (MonoRawHandle handle);
 #define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle
 
 /*
+ * TYPED_HANDLE_DECL(SomeType):
+ *   Expands to a decl for handles to SomeType and to an internal payload struct.
+ *
+ * For example, TYPED_HANDLE_DECL(MonoObject) (see below) expands to:
+ *
  * typedef struct {
  *   MonoObject *__obj;
  * } MonoObjectHandlePayload;
@@ -196,7 +201,9 @@ void mono_handle_verify (MonoRawHandle handle);
  * typedef MonoObjectHandlePayload* MonoObjectHandle;
  */
 #define TYPED_HANDLE_DECL(TYPE) typedef struct { TYPE *__obj; } TYPED_HANDLE_PAYLOAD_NAME (TYPE) ; typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_HANDLE_NAME (TYPE)
-#define MONO_HANDLE_PAYLOAD_OFFSET(TYPE) MONO_STRUCT_OFFSET(TYPED_HANDLE_PAYLOAD_NAME (TYPE), __obj)
+/* Have to double expand because MONO_STRUCT_OFFSET is doing token pasting on cross-compilers. */
+#define MONO_HANDLE_PAYLOAD_OFFSET_(PayloadType) MONO_STRUCT_OFFSET(PayloadType, __obj)
+#define MONO_HANDLE_PAYLOAD_OFFSET(TYPE) MONO_HANDLE_PAYLOAD_OFFSET_(TYPED_HANDLE_PAYLOAD_NAME (TYPE))
 
 #define MONO_HANDLE_INIT ((void*) mono_null_value_handle)
 #define NULL_HANDLE mono_null_value_handle
index 82fc1734c29102d1e84d8d806a8e0c800e430b18..60cdc39b98e3d09ea368e0cdc4c270d3985c83e1 100644 (file)
@@ -692,6 +692,7 @@ ICALL_TYPE(MARSHAL, "System.Runtime.InteropServices.Marshal", MARSHAL_2)
 #endif
 ICALL(MARSHAL_2, "AllocCoTaskMem", ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem)
 ICALL(MARSHAL_3, "AllocHGlobal", ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal)
+ICALL(MARSHAL_50, "BufferToBSTR", ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR)
 ICALL(MARSHAL_4, "DestroyStructure", ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure)
 ICALL(MARSHAL_5, "FreeBSTR", ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR)
 ICALL(MARSHAL_6, "FreeCoTaskMem", ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem)
@@ -738,6 +739,7 @@ ICALL(MARSHAL_32, "StringToHGlobalAnsi", ves_icall_System_Runtime_InteropService
 ICALL(MARSHAL_33, "StringToHGlobalUni", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni)
 ICALL(MARSHAL_34, "StructureToPtr", ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr)
 ICALL(MARSHAL_35, "UnsafeAddrOfPinnedArrayElement", ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement)
+
 ICALL(MARSHAL_41, "copy_from_unmanaged", ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged)
 ICALL(MARSHAL_42, "copy_to_unmanaged", ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged)
 
index a9d68804dc1c604fd51231fae2e4a3381da873c9..f0be6e59ab20c7653c58a74e095e04cc217108ab 100644 (file)
@@ -8717,6 +8717,8 @@ mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
 #else
        /* it wasn't found in the static call tables */
        if (!imap) {
+               if (uses_handles)
+                       *uses_handles = FALSE;
                mono_icall_unlock ();
                return NULL;
        }
index 0132f53fbed8ae08a5777249e87796ad5ee92050..b27996839e9356dd40c0496abbc451ef3723a6d6 100644 (file)
@@ -7767,7 +7767,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                MonoClass *error_class;
                int thread_info_var = -1, stack_mark_var = -1, error_var = -1;
                MonoMethodSignature *call_sig = csig;
-               gboolean uses_handles;
+               gboolean uses_handles = FALSE;
                (void) mono_lookup_internal_call_full (method, &uses_handles);
 
 
index 512d44b421193642b7ec40979bdbca756d973ae6..166db1478ce52312ca113fd954646df022247a7e 100644 (file)
@@ -275,7 +275,10 @@ gpointer
 mono_string_to_ansibstr (MonoString *string_obj);
 
 gpointer
-mono_string_to_bstr (MonoString *string_obj);
+mono_ptr_to_bstr (gpointer ptr, int slen);
+
+gpointer
+mono_string_to_bstr(MonoString* str);
 
 void mono_delegate_free_ftnptr (MonoDelegate *delegate);
 
@@ -472,6 +475,9 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString *string);
 
+gpointer
+ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (MonoArray *ptr, int len);
+
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string);
 
index 90a4d332bd129c818bebd54cb74b4e90ddd481f6..561e9968838f4a69d24e7c6eb77e273118386a88 100644 (file)
@@ -6,6 +6,7 @@
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/monitor.h>
+#include <mono/metadata/handle.h>
 #ifdef HAVE_SGEN_GC
 #include <mono/sgen/sgen-gc.h>
 #endif
index 3dfd3c4e08f720871d564e55926e9009fa568e7a..fe09d0c24b881a1c10ee7046c94cb5c5aba395e8 100644 (file)
@@ -357,7 +357,8 @@ mon_finalize (MonoThreadsSync *mon)
        LOCK_DEBUG (g_message ("%s: Finalizing sync %p", __func__, mon));
 
        if (mon->entry_sem != NULL) {
-               CloseHandle (mon->entry_sem);
+               mono_coop_sem_destroy (mon->entry_sem);
+               g_free (mon->entry_sem);
                mon->entry_sem = NULL;
        }
        /* If this isn't empty then something is seriously broken - it
@@ -679,7 +680,7 @@ mono_monitor_exit_inflated (MonoObject *obj)
                        tmp_status = InterlockedCompareExchange ((gint32*)&mon->status, new_status, old_status);
                        if (tmp_status == old_status) {
                                if (have_waiters)
-                                       ReleaseSemaphore (mon->entry_sem, 1, NULL);
+                                       mono_coop_sem_post (mon->entry_sem);
                                break;
                        }
                        old_status = tmp_status;
@@ -745,8 +746,8 @@ mono_monitor_try_enter_inflated (MonoObject *obj, guint32 ms, gboolean allow_int
        HANDLE sem;
        gint64 then = 0, now, delta;
        guint32 waitms;
-       guint32 ret;
        guint32 new_status, old_status, tmp_status;
+       MonoSemTimedwaitRet wait_ret;
        MonoInternalThread *thread;
        gboolean interrupted = FALSE;
 
@@ -838,11 +839,12 @@ retry_contended:
         */
        if (mon->entry_sem == NULL) {
                /* Create the semaphore */
-               sem = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
-               g_assert (sem != NULL);
+               sem = g_new0 (MonoCoopSem, 1);
+               mono_coop_sem_init (sem, 0);
                if (InterlockedCompareExchangePointer ((gpointer*)&mon->entry_sem, sem, NULL) != NULL) {
                        /* Someone else just put a handle here */
-                       CloseHandle (sem);
+                       mono_coop_sem_destroy (sem);
+                       g_free (sem);
                }
        }
 
@@ -878,12 +880,10 @@ retry_contended:
        mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
 
        /*
-        * We pass TRUE instead of allow_interruption since we have to check for the
+        * We pass ALERTABLE instead of allow_interruption since we have to check for the
         * StopRequested case below.
         */
-       MONO_ENTER_GC_SAFE;
-       ret = WaitForSingleObjectEx (mon->entry_sem, waitms, TRUE);
-       MONO_EXIT_GC_SAFE;
+       wait_ret = mono_coop_sem_timedwait (mon->entry_sem, waitms, MONO_SEM_FLAGS_ALERTABLE);
 
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
        
@@ -891,7 +891,7 @@ retry_contended:
        mono_perfcounters->thread_queue_len--;
 #endif
 
-       if (ret == WAIT_IO_COMPLETION && !allow_interruption) {
+       if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED && !allow_interruption) {
                interrupted = TRUE;
                /* 
                 * We have to obey a stop/suspend request even if 
@@ -914,11 +914,11 @@ retry_contended:
                        /* retry from the top */
                        goto retry_contended;
                }
-       } else if (ret == WAIT_OBJECT_0) {
+       } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
                interrupted = FALSE;
                /* retry from the top */
                goto retry_contended;
-       } else if (ret == WAIT_TIMEOUT) {
+       } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
                /* we're done */
        }
 
@@ -927,10 +927,10 @@ retry_contended:
 
        mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_FAIL);
 
-       if (ret == WAIT_IO_COMPLETION) {
+       if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
                LOCK_DEBUG (g_message ("%s: (%d) interrupted waiting, returning -1", __func__, id));
                return -1;
-       } else if (ret == WAIT_TIMEOUT) {
+       } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
                LOCK_DEBUG (g_message ("%s: (%d) timed out waiting, returning FALSE", __func__, id));
                return 0;
        } else {
index f43e08caece432d1aba4a7bedd81d8e063138ff1..39afe1b69abeb67585e596f58b0759f0e7294f07 100644 (file)
@@ -13,7 +13,8 @@
 #include <glib.h>
 #include <mono/metadata/object.h>
 #include <mono/io-layer/io-layer.h>
-#include "mono/utils/mono-compiler.h"
+#include <mono/utils/mono-compiler.h>
+#include <mono/utils/mono-coop-semaphore.h>
 
 G_BEGIN_DECLS
 
@@ -39,9 +40,9 @@ struct _MonoThreadsSync
 #ifdef HAVE_MOVING_COLLECTOR
        gint32 hash_code;
 #endif
-       HANDLE entry_sem;
        GSList *wait_list;
        void *data;
+       MonoCoopSem *entry_sem;
 };
 
 /*
index 34d9ffc1df1dcc9f41f066323529c6666403981b..67da8451d17030e15f33c538ce08eefe1afbbd6a 100644 (file)
@@ -56,6 +56,8 @@ DECL_SIZE(gpointer)
 DECL_OFFSET(MonoObject, vtable)
 DECL_OFFSET(MonoObject, synchronisation)
 
+DECL_OFFSET(MonoObjectHandlePayload, __obj)
+
 DECL_OFFSET(MonoClass, interface_bitmap)
 DECL_OFFSET(MonoClass, byval_arg)
 DECL_OFFSET(MonoClass, cast_class)
index bafaa414969ec65fa1aafd1bfbcaaa7da7307102..46b76b4fc28abd8decb995d0bbefb0707bc57b4e 100644 (file)
@@ -728,7 +728,13 @@ struct MonoBasicBlock {
        guint real_offset;
 
        GSList *seq_points;
+
+       // The MonoInst of the last sequence point for the current basic block.
        MonoInst *last_seq_point;
+       
+       // This will hold a list of last sequence points of incoming basic blocks
+       MonoInst **pred_seq_points;
+       guint num_pred_seq_points;
 
        GSList *spill_slot_defs;
 
index fd9cc01200d0c9d3ba020853ac7b3f39e9a38732..899544d1c02de3e8c90760af621a74f899d64438 100644 (file)
 #include "seq-points.h"
 
 static void
-collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int depth)
+insert_pred_seq_point (MonoInst *last_seq_ins, MonoInst *ins, GSList **next)
 {
-       int i;
        MonoBasicBlock *in_bb;
        GSList *l;
+       int src_index = last_seq_ins->backend.size;
+       int dst_index = ins->backend.size;
+
+       /* bb->in_bb might contain duplicates */
+       for (l = next [src_index]; l; l = l->next)
+               if (GPOINTER_TO_UINT (l->data) == dst_index)
+                       break;
+       if (!l)
+               next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
+}
+
+static void
+recursively_make_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+       const gpointer MONO_SEQ_SEEN_LOOP = GINT_TO_POINTER(-1);
+
+       GArray *predecessors = g_array_new (FALSE, TRUE, sizeof (gpointer));
+       GHashTable *seen = g_hash_table_new_full (g_direct_hash, NULL, NULL, NULL);
+
+       // Insert/remove sentinel into the memoize table to detect loops containing bb
+       bb->pred_seq_points = MONO_SEQ_SEEN_LOOP;
+
+       for (int i = 0; i < bb->in_count; ++i) {
+               MonoBasicBlock *in_bb = bb->in_bb [i];
+               
+               // This bb has the last seq point, append it and continue
+               if (in_bb->last_seq_point != NULL) {
+                       predecessors = g_array_append_val (predecessors, in_bb->last_seq_point);
+                       continue;
+               }
+
+               // We've looped or handled this before, exit early.
+               // No last sequence points to find.
+               if (in_bb->pred_seq_points == MONO_SEQ_SEEN_LOOP)
+                       continue;
+
+               // Take sequence points from incoming basic blocks
+       
+               if (in_bb == cfg->bb_entry)
+                       continue;
 
-       for (i = 0; i < bb->in_count; ++i) {
-               in_bb = bb->in_bb [i];
-
-               if (in_bb->last_seq_point) {
-                       int src_index = in_bb->last_seq_point->backend.size;
-                       int dst_index = ins->backend.size;
-
-                       /* bb->in_bb might contain duplicates */
-                       for (l = next [src_index]; l; l = l->next)
-                               if (GPOINTER_TO_UINT (l->data) == dst_index)
-                                       break;
-                       if (!l)
-                               next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
-               } else {
-                       /* Have to look at its predecessors */
-                       if (depth < 5)
-                               collect_pred_seq_points (in_bb, ins, next, depth + 1);
+               if (in_bb->pred_seq_points == NULL)
+                       recursively_make_pred_seq_points (cfg, in_bb);
+
+               // Union sequence points with incoming bb's
+               for (int i=0; i < in_bb->num_pred_seq_points; i++) {
+                       if (!g_hash_table_lookup (seen, in_bb->pred_seq_points [i])) {
+                               g_array_append_val (predecessors, in_bb->pred_seq_points [i]);
+                               g_hash_table_insert (seen, in_bb->pred_seq_points [i], &MONO_SEQ_SEEN_LOOP);
+                       }
                }
+               // predecessors = g_array_append_vals (predecessors, in_bb->pred_seq_points, in_bb->num_pred_seq_points);
        }
+
+       g_hash_table_destroy (seen);
+
+       if (predecessors->len != 0) {
+               bb->pred_seq_points = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst *) * predecessors->len);
+               bb->num_pred_seq_points = predecessors->len;
+
+               for (int newer = 0; newer < bb->num_pred_seq_points; newer++) {
+                       bb->pred_seq_points [newer] = g_array_index(predecessors, gpointer, newer);
+               }
+       } 
+
+       g_free (predecessors);
+}
+
+static void
+collect_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GSList **next)
+{
+       // Doesn't have a last sequence point, must find from incoming basic blocks
+       if (bb->pred_seq_points == NULL && bb != cfg->bb_entry)
+               recursively_make_pred_seq_points (cfg, bb);
+
+       for (int i = 0; i < bb->num_pred_seq_points; i++)
+               insert_pred_seq_point (bb->pred_seq_points [i], ins, next);
+
+       return;
 }
 
 void
@@ -93,7 +151,7 @@ mono_save_seq_point_info (MonoCompile *cfg)
                                        next [last->backend.size] = g_slist_append (next [last->backend.size], GUINT_TO_POINTER (ins->backend.size));
                                } else {
                                        /* Link with the last bb in the previous bblocks */
-                                       collect_pred_seq_points (bb, ins, next, 0);
+                                       collect_pred_seq_points (cfg, bb, ins, next);
                                }
 
                                last = ins;
index a22c14b08ea8e9e4d89ffcde322238f4eac55f83..ee235f5c739cb4a91bb87edfe55e0b5bb5a14f3c 100755 (executable)
@@ -18,7 +18,7 @@ RUNTIME=$BASEDIR/../../runtime/mono-wrapper
 trap "rm -rf ${TMP_FILE_PREFIX}*" EXIT
 
 tmp_file () {
-       mktemp ./${TMP_FILE_PREFIX}XXXX
+       mktemp ./${TMP_FILE_PREFIX}XXXXXX
 }
 
 clean_aot () {
index f8e557492a5fdda0111d1232ad11cdced805d78d..1cfd4fdb897ecec92dd246cf7b6bc7452b68d09f 100644 (file)
@@ -917,7 +917,7 @@ endif
 # Remove empty .stdout and .stderr files for wrench
 rm-empty-logs:
        @echo "Removing empty logs..."
-       @find . '(' -name "*.stdout" -o -name "*.stderr" ')' -empty -exec rm {} \;
+       find . '(' -name "*.stdout" -o -name "*.stderr" ')' -size 0 -exec rm {} \;
 
 assemblyresolve/test/asm.dll:
        $(MAKE) -C assemblyresolve prereq
index 67591ddcc06bb784a0a36e3d4bb8ffe61b9d36a9..7956f23a4cba228035accae07c9673698e0a89b4 100644 (file)
@@ -5,8 +5,11 @@ using System.Text;
 
 public class Tests
 {
+       private static int mainThreadId;
+
        public static int Main ()
        {
+               mainThreadId = Thread.CurrentThread.ManagedThreadId;
                return TestDriver.RunTests (typeof (Tests));
        }
 
@@ -21,6 +24,46 @@ public class Tests
                        Thread.CurrentThread.Priority.ToString());
        }
        
+       public static int test_0_main_thread_priority ()
+       {
+               Console.WriteLine("Testing main thread's priority");
+               if (Thread.CurrentThread.ManagedThreadId != mainThreadId)
+               {
+                       Console.WriteLine("test_0_main_thread_priority() must be run on the main thread");
+                       return 1;
+               }
+
+               var before = Thread.CurrentThread.Priority;
+               Console.WriteLine("Priority: {0}", before);
+               if (before != ThreadPriority.Normal)
+                       return 2;
+
+               Console.WriteLine("Setting main thread's priority to AboveNormal");
+               Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
+               var after = Thread.CurrentThread.Priority;
+               Console.WriteLine("Priority: {0} {1}", before, after);
+               if (after != ThreadPriority.AboveNormal)
+                       return 3;
+
+               before = after;
+               Console.WriteLine("Setting main thread's priority to BelowNormal");
+               Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
+               after = Thread.CurrentThread.Priority;
+               Console.WriteLine("Priority: {0} {1}", before, after);
+               if (after != ThreadPriority.BelowNormal)
+                       return 4;
+
+               before = after;
+               Console.WriteLine("Setting main thread's priority to Normal");
+               Thread.CurrentThread.Priority = ThreadPriority.Normal;
+               after = Thread.CurrentThread.Priority;
+               Console.WriteLine("Priority: {0} {1}", before, after);
+               if (after != ThreadPriority.Normal)
+                       return 5;
+
+               return 0;
+       }
+
        public static int test_0_thread_priority () 
        {
                int res = 0;
index 034200d3173aad0a237c32cacca1de5785d616f7..b926791f0621f7dd5e0a57dba29569ae6b10815a 100644 (file)
@@ -121,6 +121,8 @@ mono_threads_suspend_begin_async_resume (MonoThreadInfo *info)
 void
 mono_threads_suspend_register (MonoThreadInfo *info)
 {
+       g_assert (!info->handle);
+       info->handle = mono_threads_platform_open_handle();
 }
 
 void
@@ -135,6 +137,7 @@ mono_threads_suspend_free (MonoThreadInfo *info)
 typedef struct {
        LPTHREAD_START_ROUTINE start_routine;
        void *arg;
+       gint32 priority;
        MonoCoopSem registered;
        gboolean suspend;
        HANDLE suspend_event;
@@ -156,6 +159,8 @@ inner_start_thread (LPVOID arg)
        info->runtime_thread = TRUE;
        info->create_suspended = suspend;
 
+       mono_threads_platform_set_priority(info, start_info->priority);
+
        mono_coop_sem_post (&(start_info->registered));
 
        if (suspend) {
@@ -184,6 +189,7 @@ mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg
                return NULL;
        mono_coop_sem_init (&(start_info->registered), 0);
        start_info->arg = arg;
+       start_info->priority = tp->priority;
        start_info->start_routine = start_routine;
        start_info->suspend = creation_flags & CREATE_SUSPENDED;
        creation_flags &= ~CREATE_SUSPENDED;
@@ -388,12 +394,14 @@ mono_threads_platform_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle)
 MonoThreadPriority
 mono_threads_platform_get_priority (MonoThreadInfo *info)
 {
+       g_assert (info->handle);
        return GetThreadPriority (info->handle) + 2;
 }
 
 gboolean
 mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority)
 {
+       g_assert (info->handle);
        return SetThreadPriority (info->handle, priority - 2);
 }
 
index 5d9eb574eb28201bb5aa78ca9bb9bb22be6a29f4..e04a23809a5428a760d06b8225467abacd3bbdaf 100644 (file)
@@ -754,6 +754,7 @@ namespace CppSharp
             var types = new List<string>
             {
                 "MonoObject",
+               "MonoObjectHandlePayload",
                 "MonoClass",
                 "MonoVTable",
                 "MonoDelegate",