Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@@ -0,0 +1,95 @@
//------------------------------------------------------------------------------
// <copyright file="ActivityIdHelper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
using System.Diagnostics.Tracing;
using System.Runtime.CompilerServices;
using System.Threading;
internal sealed class ActivityIdHelper {
private delegate Guid GetCurrentDelegate();
private delegate void SetAndDestroyDelegate(Guid activityId);
private delegate void SetAndPreserveDelegate(Guid activityId, out Guid oldActivityThatWillContinue);
// Note to callers: this field can be null.
internal static readonly ActivityIdHelper Instance = GetSingleton();
private static readonly Guid _baseGuid = Guid.NewGuid();
private static long _counter;
private readonly GetCurrentDelegate _getCurrentDel;
private readonly SetAndDestroyDelegate _setAndDestroyDel;
private readonly SetAndPreserveDelegate _setAndPreserveDel;
// use the factory to create an instance of this type
private ActivityIdHelper(GetCurrentDelegate getCurrentDel, SetAndDestroyDelegate setAndDestroyDel, SetAndPreserveDelegate setAndPreserveDel) {
_getCurrentDel = getCurrentDel;
_setAndDestroyDel = setAndDestroyDel;
_setAndPreserveDel = setAndPreserveDel;
}
// Gets the current thread's activity ID.
public Guid CurrentThreadActivityId {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _getCurrentDel(); }
}
private static ActivityIdHelper GetSingleton() {
try {
// The mscorlib APIs we depend on weren't added until Blue, so we can't
// take a direct dependency. Need to light up instead.
var getCurrentDel = (GetCurrentDelegate)Delegate.CreateDelegate(
typeof(GetCurrentDelegate), typeof(EventSource), "get_CurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
var setAndDestroyDel = (SetAndDestroyDelegate)Delegate.CreateDelegate(
typeof(SetAndDestroyDelegate), typeof(EventSource), "SetCurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
var setAndPreserveDel = (SetAndPreserveDelegate)Delegate.CreateDelegate(
typeof(SetAndPreserveDelegate), typeof(EventSource), "SetCurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
if (getCurrentDel != null && setAndDestroyDel != null && setAndPreserveDel != null) {
return new ActivityIdHelper(getCurrentDel, setAndDestroyDel, setAndPreserveDel);
}
}
catch {
// exceptions are not fatal; we just won't be able to call the new APIs
}
return null;
}
// Disposes of the thread's existing activity ID, then sets the new activity ID on this thread.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetCurrentThreadActivityId(Guid activityId) {
_setAndDestroyDel(activityId);
}
// Suspends (but does not dispose of) the thread's existing activity ID, then sets a new activity ID on this thread.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue) {
_setAndPreserveDel(activityId, out oldActivityThatWillContinue);
}
// !! SECURITY WARNING !!
// The GUIDs created by this method are predictable and should be used ONLY for tracing.
// Any other use (such as leaking them to the user) constitutes information disclosure.
//
// This is a perf-sensitive method since it could potentially be called many times per
// request. Guid.NewGuid() is slow since it eventually calls CAPI, and we did actually
// see it show up as a bottleneck when developing MVC 2. The below implementation has
// measurably better performance characteristics than calling the other Guid ctors.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Guid UnsafeCreateNewActivityId() {
Guid guidCopy = _baseGuid;
*(long*)(&guidCopy) ^= Interlocked.Increment(ref _counter); // operate on the copy, not the original
return guidCopy;
}
}
}

View File

@@ -0,0 +1,469 @@
//------------------------------------------------------------------------------
// <copyright file="AppSettings.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
// AppSettings.cs
//
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.Security.Permissions;
using System.Web.Configuration;
using System.Web.Hosting;
namespace System.Web.Util {
internal static class AppSettings
{
private static volatile bool _settingsInitialized = false;
private static object _appSettingsLock = new object();
private static void EnsureSettingsLoaded() {
if (!_settingsInitialized) {
lock (_appSettingsLock) {
if (!_settingsInitialized) {
NameValueCollection settings = null;
try {
settings = GetAppSettingsSection();
} finally {
// GetApplicationPathData may throw. That's fine. Let the user see the exception
// once, but just fall back on default settings for the future.
if (settings == null || !Boolean.TryParse(settings["aspnet:UseHostHeaderForRequestUrl"], out _useHostHeaderForRequestUrl))
_useHostHeaderForRequestUrl = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowAnonymousImpersonation"], out _allowAnonymousImpersonation))
_allowAnonymousImpersonation = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:ScriptResourceAllowNonJsFiles"], out _scriptResourceAllowNonJsFiles))
_scriptResourceAllowNonJsFiles = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyEncryption"], out _useLegacyEncryption))
_useLegacyEncryption = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyMachineKeyEncryption"], out _useLegacyMachineKeyEncryption))
_useLegacyMachineKeyEncryption = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyFormsAuthenticationTicketCompatibility"], out _useLegacyFormsAuthenticationTicketCompatibility))
_useLegacyFormsAuthenticationTicketCompatibility = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyEventValidationCompatibility"], out _useLegacyEventValidationCompatibility))
_useLegacyEventValidationCompatibility = false;
_allowInsecureDeserialization = GetNullableBooleanValue(settings, "aspnet:AllowInsecureDeserialization");
if (settings == null || !Boolean.TryParse(settings["aspnet:AlwaysIgnoreViewStateValidationErrors"], out _alwaysIgnoreViewStateValidationErrors))
_alwaysIgnoreViewStateValidationErrors = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowRelaxedHttpUserName"], out _allowRelaxedHttpUserName))
_allowRelaxedHttpUserName = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:JavaScriptDoNotEncodeAmpersand"], out _javaScriptDoNotEncodeAmpersand))
_javaScriptDoNotEncodeAmpersand = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:UseTaskFriendlySynchronizationContext"], out _useTaskFriendlySynchronizationContext))
_useTaskFriendlySynchronizationContext = (BinaryCompatibility.Current.TargetsAtLeastFramework45) ? true : false;
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowAsyncDuringSyncStages"], out _allowAsyncDuringSyncStages))
_allowAsyncDuringSyncStages = false;
if (settings == null || !int.TryParse(settings["aspnet:MaxHttpCollectionKeys"], out _maxHttpCollectionKeys) || _maxHttpCollectionKeys < 0)
_maxHttpCollectionKeys = DefaultMaxHttpCollectionKeys;
if (settings == null || !int.TryParse(settings["aspnet:MaxJsonDeserializerMembers"], out _maxJsonDeserializerMembers) || _maxJsonDeserializerMembers < 0)
_maxJsonDeserializerMembers = DefaultMaxJsonDeserializerMembers;
if (settings == null || !Boolean.TryParse(settings["aspnet:DoNotDisposeSpecialHttpApplicationInstances"], out _doNotDisposeSpecialHttpApplicationInstances))
_doNotDisposeSpecialHttpApplicationInstances = false;
if (settings != null)
_formsAuthReturnUrlVar = settings["aspnet:FormsAuthReturnUrlVar"];
if (settings == null || !Boolean.TryParse(settings["aspnet:RestrictXmlControls"], out _restrictXmlControls))
_restrictXmlControls = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowRelaxedRelativeUrl"], out _allowRelaxedRelativeUrl))
_allowRelaxedRelativeUrl = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyRequestUrlGeneration"], out _useLegacyRequestUrlGeneration))
_useLegacyRequestUrlGeneration = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowUtf7RequestContentEncoding"], out _allowUtf7RequestContentEncoding))
_allowUtf7RequestContentEncoding = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowRelaxedUnicodeDecoding"], out _allowRelaxedUnicodeDecoding))
_allowRelaxedUnicodeDecoding = false;
if (settings == null || !Boolean.TryParse(settings["aspnet:DontUsePercentUUrlEncoding"], out _dontUsePercentUUrlEncoding))
_dontUsePercentUUrlEncoding = BinaryCompatibility.Current.TargetsAtLeastFramework452; // default value is keyed off of <httpRuntime targetFramework="4.5.2" />
if (settings == null || !int.TryParse(settings["aspnet:UpdatePanelMaxScriptLength"], out _updatePanelMaxScriptLength) || _updatePanelMaxScriptLength < 0)
_updatePanelMaxScriptLength = 0;
// AppSettings override allows users to build against 4.5 but run against 4.0 or 4.5
_maxConcurrentCompilations = GetNullableIntegerValue(settings, "aspnet:MaxConcurrentCompilations");
if (settings == null || !int.TryParse(settings["aspnet:MaxAcceptLanguageFallbackCount"], out _maxAcceptLanguageFallbackCount) || _maxAcceptLanguageFallbackCount <= 0)
_maxAcceptLanguageFallbackCount = DefaultMaxAcceptLanguageFallbackCount;
if (settings == null || !Boolean.TryParse(settings["aspnet:PortableCompilationOutput"], out _portableCompilationOutput))
_portableCompilationOutput = false;
if (settings == null || string.IsNullOrWhiteSpace(_portableCompilationOutputSnapshotType = settings["aspnet:PortableCompilationOutputSnapshotType"]))
_portableCompilationOutputSnapshotType = null;
if (settings == null || string.IsNullOrWhiteSpace(_portableCompilationOutputSnapshotTypeOptions = settings["aspnet:PortableCompilationOutputSnapshotTypeOptions"]))
_portableCompilationOutputSnapshotTypeOptions = null;
if (settings == null || !Boolean.TryParse(settings["aspnet:EnsureSessionStateLockedOnFlush"], out _ensureSessionStateLockedOnFlush))
_ensureSessionStateLockedOnFlush = false;
_settingsInitialized = true;
}
}
}
}
}
[ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
[SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "This assert is safe since we control the callers; they're not leaking information.")]
private static NameValueCollection GetAppSettingsSection() {
// DevDiv #353926 - Fall back to reading App.config if System.Web types are being consumed outside an ASP.NET application
if (!HostingEnvironment.IsHosted) {
return ConfigurationManager.AppSettings;
}
// Check the app-level config. Ignore configuration errors
CachedPathData appPathData = CachedPathData.GetApplicationPathData();
if (appPathData != null && appPathData.ConfigRecord != null)
return appPathData.ConfigRecord.GetSection("appSettings") as NameValueCollection;
// nothing found
return null;
}
// helper function to read a tri-state boolean from config
private static bool? GetNullableBooleanValue(NameValueCollection settings, string key) {
bool value;
return (settings != null && Boolean.TryParse(settings[key], out value)) ? value : (bool?)null;
}
// helper function to read a nullable int from config
private static int? GetNullableIntegerValue(NameValueCollection settings, string key) {
int value;
return (settings != null && int.TryParse(settings[key], out value)) ? value : (int?)null;
}
private static bool _useHostHeaderForRequestUrl;
internal static bool UseHostHeaderForRequestUrl {
get {
EnsureSettingsLoaded();
return _useHostHeaderForRequestUrl;
}
}
private static bool _allowAnonymousImpersonation;
internal static bool AllowAnonymousImpersonation {
get {
EnsureSettingsLoaded();
return _allowAnonymousImpersonation;
}
}
// false [default] to allow ScriptResource.axd to serve static files only if they are *.js;
// true to allow ScriptResource.axd to serve any static file (bad practice)
private static bool _scriptResourceAllowNonJsFiles;
internal static bool ScriptResourceAllowNonJsFiles {
get {
EnsureSettingsLoaded();
return _scriptResourceAllowNonJsFiles;
}
}
// false [default] to use encrypt+sign for all except Membership and MachineKey public API
// true to use encrypt only (dangerous!)
private static bool _useLegacyEncryption;
internal static bool UseLegacyEncryption {
get {
EnsureSettingsLoaded();
return _useLegacyEncryption;
}
}
// false [default] to use encrypt+sign for MachineKey public API
// true to use encrypt only for MachineKey public API (dangerous!)
private static bool _useLegacyMachineKeyEncryption;
internal static bool UseLegacyMachineKeyEncryption {
get {
EnsureSettingsLoaded();
return _useLegacyMachineKeyEncryption;
}
}
// false [default] to use secure semantics when generating FormsAuthentication tickets
// true to allow ticketCompatibilityMode="Framework20" (dangerous!)
private static bool _useLegacyFormsAuthenticationTicketCompatibility;
internal static bool UseLegacyFormsAuthenticationTicketCompatibility {
get {
EnsureSettingsLoaded();
return _useLegacyFormsAuthenticationTicketCompatibility;
}
}
// false [default] to use a cryptographic hash algorithm when generating the __EVENTVALIDATION field
// true to use String.GetHashCode() instead (dangerous!)
// more info: DevDiv #233564 (http://vstfdevdiv:8080/DevDiv2/web/wi.aspx?id=233564)
private static bool _useLegacyEventValidationCompatibility;
internal static bool UseLegacyEventValidationCompatibility {
get {
EnsureSettingsLoaded();
return _useLegacyEventValidationCompatibility;
}
}
// false to always enforce EnableViewStateMac=false
// true to allow the developer to specify EnableViewStateMac=false (dangerous, leads to RCE!)
// null [default] to make the decision based on a registry key
// more info: DevDiv #461378 (http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/461378)
private static bool? _allowInsecureDeserialization;
internal static bool? AllowInsecureDeserialization {
get {
EnsureSettingsLoaded();
return _allowInsecureDeserialization;
}
}
// false [default] to use the default heuristic for determining when to suppress __VIEWSTATE MAC validation errors and when to display a YSOD
// true to always ---- errors and never show a YSOD
private static bool _alwaysIgnoreViewStateValidationErrors;
internal static bool AlwaysIgnoreViewStateValidationErrors {
get {
EnsureSettingsLoaded();
return _alwaysIgnoreViewStateValidationErrors;
}
}
// false [default] to restrict dangerous characters in any user name passed to native code
// true to allow dangerous characters
private static bool _allowRelaxedHttpUserName;
internal static bool AllowRelaxedHttpUserName {
get {
EnsureSettingsLoaded();
return _allowRelaxedHttpUserName;
}
}
// false [default] to encode '&' characters in HttpUtility.JavaScriptStringEncode()
// true to not encode '&' characters (bad practice)
private static bool _javaScriptDoNotEncodeAmpersand;
internal static bool JavaScriptDoNotEncodeAmpersand {
get {
EnsureSettingsLoaded();
return _javaScriptDoNotEncodeAmpersand;
}
}
// false [default] to use the updated AspNetSynchronizationContext type (needed for TAP methods)
// true to use LegacyAspNetSynchronizationContext (needed for some back-compat scenarios)
private static bool _useTaskFriendlySynchronizationContext ;
internal static bool UseTaskFriendlySynchronizationContext {
get {
EnsureSettingsLoaded();
return _useTaskFriendlySynchronizationContext ;
}
}
// false [default] if the updated AspNetSynchronizationContext type should throw when it encounters invalid operations
// true to allow some invalid operations through the system (needed for some back-compat scenarios)
// more info: see doc on HttpContext.AllowAsyncDuringSyncStages
private static bool _allowAsyncDuringSyncStages;
internal static bool AllowAsyncDuringSyncStages {
get {
EnsureSettingsLoaded();
return _allowAsyncDuringSyncStages;
}
}
// maximum number of keys a HttpValueCollection, HttpFileCollection or HttpCookieCollection is allowed to have
private const int DefaultMaxHttpCollectionKeys = Int32.MaxValue;
private static int _maxHttpCollectionKeys = DefaultMaxHttpCollectionKeys;
internal static int MaxHttpCollectionKeys {
get {
EnsureSettingsLoaded();
return _maxHttpCollectionKeys;
}
}
// maximum number of entries a Json deserialized dictionary is allowed to have
private const int DefaultMaxJsonDeserializerMembers = Int32.MaxValue;
private static int _maxJsonDeserializerMembers = DefaultMaxJsonDeserializerMembers;
internal static int MaxJsonDeserializerMembers {
get {
EnsureSettingsLoaded();
return _maxJsonDeserializerMembers;
}
}
// false [default] to call HttpApplication.Dispose() on all HttpApplication instances instantiated by ASP.NET
// true to suppress calling HttpApplication.Dispose() on "special" (i.e., associated with App_Start, App_End, etc.) HttpApplication instances
// see DevDiv #109006 (http://vstfdevdiv:8080/DevDiv2/web/wi.aspx?id=109006): HttpModules attached to the "Special" HttpApplication instance are not disposed
private static bool _doNotDisposeSpecialHttpApplicationInstances;
internal static bool DoNotDisposeSpecialHttpApplicationInstances {
get {
EnsureSettingsLoaded();
return _doNotDisposeSpecialHttpApplicationInstances;
}
}
// none [default] to use the existing /loging.aspx?ReturnUrl=
// <FormsAuthReturnUrlVar> to use /loging.aspx?<FormsAuthReturnUrlVar>=
private static string _formsAuthReturnUrlVar;
internal static string FormsAuthReturnUrlVar {
get {
EnsureSettingsLoaded();
return _formsAuthReturnUrlVar;
}
}
// false [default] to use potentially unsafe System.Xml API's that were in use for 1.0 through 4.0
// true to avoid using vulnerable System.Xml API's.
private static bool _restrictXmlControls;
internal static bool RestrictXmlControls {
get {
EnsureSettingsLoaded();
return _restrictXmlControls;
}
}
// false [default] - requires relative url to be more strict
// true - use less strict policy
private static bool _allowRelaxedRelativeUrl;
internal static bool AllowRelaxedRelativeUrl {
get {
EnsureSettingsLoaded();
return _allowRelaxedRelativeUrl;
}
}
// false [default] - attempts to re-encode HttpRequest.Url so that it is equivalent to the actual incoming URL
// true - does not attempt to re-encode the Url, which could allow the Uri class to perform double-decoding (dangerous!)
// See also DevDiv #703232 (http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/703232)
private static bool _useLegacyRequestUrlGeneration;
internal static bool UseLegacyRequestUrlGeneration {
get {
EnsureSettingsLoaded();
return _useLegacyRequestUrlGeneration;
}
}
// false [default] - disallow UTF-7 as an incoming ContentEncoding
// true - allow UTF-7 as an incoming ContentEncoding (dangerous!)
private static bool _allowUtf7RequestContentEncoding;
internal static bool AllowUtf7RequestContentEncoding {
get {
EnsureSettingsLoaded();
return _allowUtf7RequestContentEncoding;
}
}
// false [default] - disallow invalid UTF-16 (like unpaired surrogates) when deserializing JSON strings and inside UrlDecode
// true - allow malformed strings like "\ud800" and "%ud800" to be deserialized (dangerous!)
private static bool _allowRelaxedUnicodeDecoding;
internal static bool AllowRelaxedUnicodeDecoding {
get {
EnsureSettingsLoaded();
return _allowRelaxedUnicodeDecoding;
}
}
// false - use UrlEncodeUnicode for some URL generation within ASP.NET, which can produce non-compliant results
// true - use UTF8 encoding for things like <form action>, which works with modern browsers
// defaults to true when targeting >= 4.5.2, otherwise false
// See DevDiv #762975 for more information.
private static bool _dontUsePercentUUrlEncoding;
internal static bool DontUsePercentUUrlEncoding {
get {
EnsureSettingsLoaded();
return _dontUsePercentUUrlEncoding;
}
}
// maximum length for UpdatePanel script block
private static int _updatePanelMaxScriptLength;
internal static int UpdatePanelMaxScriptLength {
get {
EnsureSettingsLoaded();
return _updatePanelMaxScriptLength;
}
}
// maximum number of concurrent compilations
private static int? _maxConcurrentCompilations;
internal static int? MaxConcurrentCompilations {
get {
EnsureSettingsLoaded();
return _maxConcurrentCompilations;
}
}
// Controls how deep we look when trying to get a CultureInfo from an Accept-Language header.
// For example, a value of 3 with Accept-Language: en-us, en, fr-FR, zh-CN will cause us to
// look for "en-us", "en", and "fr-FR" in order, taking the first hit, but we won't look
// for "zh-CN" if the first three fail. Setting this value too high could result in DoS.
private const int DefaultMaxAcceptLanguageFallbackCount = 3;
private static int _maxAcceptLanguageFallbackCount;
internal static int MaxAcceptLanguageFallbackCount {
get {
EnsureSettingsLoaded();
return _maxAcceptLanguageFallbackCount;
}
}
// false [default]
// true to allow
private static bool _portableCompilationOutput;
internal static bool PortableCompilationOutput {
get {
EnsureSettingsLoaded();
return _portableCompilationOutput;
}
}
// null [default]
// complete type name as string
private static string _portableCompilationOutputSnapshotType;
internal static string PortableCompilationOutputSnapshotType {
get {
EnsureSettingsLoaded();
return _portableCompilationOutputSnapshotType;
}
}
// null [default]
// options
private static string _portableCompilationOutputSnapshotTypeOptions;
internal static string PortableCompilationOutputSnapshotTypeOptions {
get {
EnsureSettingsLoaded();
return _portableCompilationOutputSnapshotTypeOptions;
}
}
// false [default] - allow delayed store of session state item (possibly concurrent access on new session)
// true - ensure the session state item is stored before another request is allowed to proceed with the same session
private static bool _ensureSessionStateLockedOnFlush;
internal static bool EnsureSessionStateLockedOnFlush {
get {
EnsureSettingsLoaded();
return _ensureSessionStateLockedOnFlush;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
namespace System.Web.Util {
using System;
// IMPORTANT: Each error code must be used in *exactly one place* in order to make
// diagnosing the failure easier.
internal enum AppVerifierErrorCode {
Ok,
/* ASYNC OPERATIONS */
HttpApplicationInstanceWasNull,
BeginHandlerDelegateWasNull,
AsyncCallbackInvokedMultipleTimes,
AsyncCallbackInvokedWithNullParameter,
AsyncCallbackGivenAsyncResultWhichWasNotCompleted,
AsyncCallbackInvokedSynchronouslyButAsyncResultWasNotMarkedCompletedSynchronously,
AsyncCallbackInvokedAsynchronouslyButAsyncResultWasMarkedCompletedSynchronously,
AsyncCallbackInvokedWithUnexpectedAsyncResultInstance,
AsyncCallbackInvokedAsynchronouslyThenBeginHandlerThrew,
BeginHandlerThrewThenAsyncCallbackInvokedAsynchronously,
AsyncCallbackInvokedSynchronouslyThenBeginHandlerThrew,
AsyncCallbackInvokedWithUnexpectedAsyncResultAsyncState,
AsyncCallbackCalledAfterHttpApplicationReassigned,
BeginHandlerReturnedNull,
BeginHandlerReturnedAsyncResultMarkedCompletedSynchronouslyButWhichWasNotCompleted,
BeginHandlerReturnedAsyncResultMarkedCompletedSynchronouslyButAsyncCallbackNeverCalled,
BeginHandlerReturnedUnexpectedAsyncResultInstance,
BeginHandlerReturnedUnexpectedAsyncResultAsyncState,
SyncContextSendOrPostCalledAfterRequestCompleted
}
}

View File

@@ -0,0 +1,32 @@
namespace System.Web.Util {
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
// Thrown when the AppVerifier fails an assert.
// This type is used solely as a support / diagnostics tool and will never appear over the normal course of an application.
// Specifically, it will never cross an AppDomain boundary, and we don't want to mark it as [Serializable] since that is
// essentially a public contract, and the AppVerifier feature has no public API surface. We want to retain the ability to
// change this feature on a whim without risk of breaking anybody.
[SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable", Justification = "Doesn't need to be serializable.")]
internal sealed class AppVerifierException : Exception {
private readonly AppVerifierErrorCode _errorCode;
public AppVerifierException(AppVerifierErrorCode errorCode, string message)
: base(message) {
_errorCode = errorCode;
}
private AppVerifierException(SerializationInfo info, StreamingContext context) : base(info, context) { }
public AppVerifierErrorCode ErrorCode {
get {
return _errorCode;
}
}
}
}

View File

@@ -0,0 +1,164 @@
//------------------------------------------------------------------------------
// <copyright file="ArglessEventHandlerProxy.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Permissions;
using System.Security;
/*
* Proxy that provides EventHandler and redirects it to arg-less method on the given object
*/
internal class ArglessEventHandlerProxy {
private Object _target;
private MethodInfo _arglessMethod;
internal ArglessEventHandlerProxy(Object target, MethodInfo arglessMethod) {
Debug.Assert(arglessMethod.GetParameters().Length == 0);
_target = target;
_arglessMethod = arglessMethod;
}
[ReflectionPermission(SecurityAction.Assert, Flags=ReflectionPermissionFlag.RestrictedMemberAccess)]
internal void Callback(Object sender, EventArgs e) {
_arglessMethod.Invoke(_target, new Object[0]);
}
internal EventHandler Handler {
get {
return new EventHandler(Callback);
}
}
}
internal delegate void VoidMethod();
internal class CalliEventHandlerDelegateProxy {
private delegate void ParameterlessDelegate();
private delegate void ParameterfulDelegate(object sender, EventArgs e);
private IntPtr _functionPointer;
private Object _target;
private bool _argless;
internal CalliEventHandlerDelegateProxy(Object target, IntPtr functionPointer, bool argless) {
_argless = argless;
_target = target;
_functionPointer = functionPointer;
}
internal void Callback(Object sender, EventArgs e) {
if (_argless) {
ParameterlessDelegate del = FastDelegateCreator<ParameterlessDelegate>.BindTo(_target, _functionPointer);
del();
}
else {
ParameterfulDelegate del = FastDelegateCreator<ParameterfulDelegate>.BindTo(_target, _functionPointer);
del(sender, e);
}
}
internal EventHandler Handler {
get {
return new EventHandler(Callback);
}
}
}
#if LCG_Implementation
internal delegate void ArglessMethod(IntPtr methodPtr, Object target);
internal delegate void EventArgMethod(IntPtr methodPtr, Object target, Object source, EventArgs e);
internal class CalliHelper {
internal static ArglessMethod ArglessFunctionCaller;
internal static EventArgMethod EventArgFunctionCaller;
// Make sure we have reflection permission to use ReflectionEmit and access method
[ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.ReflectionEmit | ReflectionPermissionFlag.MemberAccess)]
static CalliHelper() {
// generate void(void) calli
DynamicMethod dm = new DynamicMethod("void_calli",
typeof(void),
new Type[] { typeof(IntPtr) /* function ptr */, typeof(Object) /* target */},
typeof(CalliHelper).Module);
ILGenerator ilg = dm.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Ldarg_0);
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[0], null);
ilg.Emit(OpCodes.Ret);
ArglessFunctionCaller = (ArglessMethod)dm.CreateDelegate(typeof(ArglessMethod));
// generate void(Object, EventArgs) calli
dm = new DynamicMethod("eventarg_calli",
typeof(void),
new Type[] { typeof(IntPtr) /* function ptr */, typeof(Object) /* target */, typeof(Object) /* sender */, typeof(EventArgs) },
typeof(CalliHelper).Module);
ilg = dm.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Ldarg_2);
ilg.Emit(OpCodes.Ldarg_3);
ilg.Emit(OpCodes.Ldarg_0);
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[] { typeof(object) /* sender */, typeof(EventArgs) }, null);
ilg.Emit(OpCodes.Ret);
EventArgFunctionCaller = (EventArgMethod)dm.CreateDelegate(typeof(EventArgMethod));
}
}
#endif //LCG_Implementation
#if Reflection_Emit_Implementation
internal delegate void ArglessMethod(IntPtr methodPtr, Object target);
internal delegate void EventArgMethod(IntPtr methodPtr, Object target, Object source, EventArgs e);
internal class CalliHelper {
internal static ArglessMethod ArglessFunctionCaller;
internal static EventArgMethod EventArgFunctionCaller;
// Make sure we have reflection permission to use ReflectionEmit and access method
[ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.ReflectionEmit | ReflectionPermissionFlag.MemberAccess)]
static CalliHelper() {
AssemblyName an = new AssemblyName("CalliHelper");
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder mb = ab.DefineDynamicModule("CalliHelper.dll");
ConstructorInfo ci = typeof(CLSCompliantAttribute).GetConstructor(new Type[] { typeof(bool) });
CustomAttributeBuilder cb = new CustomAttributeBuilder(ci, new object[] { true });
mb.SetCustomAttribute(cb);
TypeBuilder tb = mb.DefineType("System.Web.Util.CalliHelper", TypeAttributes.NotPublic | TypeAttributes.Sealed);
MethodBuilder methb = tb.DefineMethod("EventArgMethod", MethodAttributes.Assembly | MethodAttributes.Static, typeof(void), new Type[] { typeof(IntPtr), typeof(object), typeof(object), typeof(EventArgs) });
ILGenerator ilg = methb.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Ldarg_2);
ilg.Emit(OpCodes.Ldarg_3);
ilg.Emit(OpCodes.Ldarg_0);
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[] { typeof(object), typeof(EventArgs) }, null);
ilg.Emit(OpCodes.Ret);
methb = tb.DefineMethod("ArglessMethod", MethodAttributes.Assembly | MethodAttributes.Static, typeof(void), new Type[] { typeof (IntPtr), typeof(object) });
ilg = methb.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Ldarg_0);
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[0], null);
ilg.Emit(OpCodes.Ret);
Type t = tb.CreateType();
ArglessFunctionCaller = (ArglessMethod)Delegate.CreateDelegate(typeof(ArglessMethod), t, "ArglessMethod", true);
EventArgFunctionCaller = (EventArgMethod)Delegate.CreateDelegate(typeof(EventArgMethod), t, "EventArgMethod", true);
//ab.Save("CalliHelper.dll");
}
}
#endif // Reflection_Emit_Implementation
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
// <copyright file="AssemblyUtil.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
namespace System.Web.Util {
internal static class AssemblyUtil {
private const string _emptyFileVersion = "0.0.0.0";
public static string GetAssemblyFileVersion(Assembly assembly) {
AssemblyFileVersionAttribute[] attributes =
(AssemblyFileVersionAttribute[])assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false);
string version;
if (attributes.Length > 0) {
version = attributes[0].Version;
if (String.IsNullOrEmpty(version)) {
version = _emptyFileVersion;
}
}
else {
version = _emptyFileVersion;
}
return version;
}
}
}

View File

@@ -0,0 +1,42 @@
//------------------------------------------------------------------------------
// <copyright file="BinaryCompatibility.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
using System.Runtime.Versioning;
// This class contains utility methods that mimic the mscorlib internal System.Runtime.Versioning.BinaryCompatibility type.
internal sealed class BinaryCompatibility {
// We need to use this AppDomain key instead of AppDomainSetup.TargetFrameworkName since we don't want applications
// which happened to set TargetFrameworkName and are calling into ASP.NET APIs to suddenly start getting new behaviors.
internal const string TargetFrameworkKey = "ASPNET_TARGETFRAMEWORK";
// quick accessor for the current AppDomain's instance
public static readonly BinaryCompatibility Current = new BinaryCompatibility(AppDomain.CurrentDomain.GetData(TargetFrameworkKey) as FrameworkName);
public BinaryCompatibility(FrameworkName frameworkName) {
// parse version from FrameworkName, otherwise use a default value
Version version = VersionUtil.FrameworkDefault;
if (frameworkName != null && frameworkName.Identifier == ".NETFramework") {
version = frameworkName.Version;
}
TargetFramework = version;
TargetsAtLeastFramework45 = (version >= VersionUtil.Framework45);
TargetsAtLeastFramework451 = (version >= VersionUtil.Framework451);
TargetsAtLeastFramework452 = (version >= VersionUtil.Framework452);
}
public bool TargetsAtLeastFramework45 { get; private set; }
public bool TargetsAtLeastFramework451 { get; private set; }
public bool TargetsAtLeastFramework452 { get; private set; }
public Version TargetFramework { get; private set; }
}
}

View File

@@ -0,0 +1,102 @@
//------------------------------------------------------------------------------
// <copyright file="CancellationTokenHelper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
using System.Threading;
// Helper class for dealing with CancellationToken instances. Our Cancel and Dispose methods
// are fully thread-safe and will never block or throw, while a normal CancellationTokenSource
// doesn't make these guarantees.
internal sealed class CancellationTokenHelper : IDisposable {
private const int STATE_CREATED = 0;
private const int STATE_CANCELING = 1;
private const int STATE_CANCELED = 2;
private const int STATE_DISPOSING = 3;
private const int STATE_DISPOSED = 4; // terminal state
// A CancellationTokenHelper which is already marked as disposed; useful for avoiding
// allocations of CancellationTokenHelper instances which are never observed.
internal static readonly CancellationTokenHelper StaticDisposed = GetStaticDisposedHelper();
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private int _state;
public CancellationTokenHelper(bool canceled) {
if (canceled) {
_cts.Cancel();
}
_state = (canceled) ? STATE_CANCELED : STATE_CREATED;
}
internal bool IsCancellationRequested {
get { return _cts.IsCancellationRequested; }
}
internal CancellationToken Token {
get { return _cts.Token; }
}
// Cancels the token.
public void Cancel() {
if (Interlocked.CompareExchange(ref _state, STATE_CANCELING, STATE_CREATED) == STATE_CREATED) {
// Only allow cancellation if the token hasn't yet been canceled or disposed.
// Cancel on a ThreadPool thread so that we can release the original thread back to IIS.
// We can use UnsafeQUWI to avoid an extra ExecutionContext capture since CancellationToken already captures it.
ThreadPool.UnsafeQueueUserWorkItem(_ => {
try {
_cts.Cancel();
}
catch {
// ---- all exceptions to avoid killing the worker process.
}
finally {
if (Interlocked.CompareExchange(ref _state, STATE_CANCELED, STATE_CANCELING) == STATE_DISPOSING) {
// A call to Dispose() came in on another thread while we were in the middle of a cancel
// operation. That thread will no-op, so we'll dispose of it here.
_cts.Dispose();
Interlocked.Exchange(ref _state, STATE_DISPOSED);
}
}
}, null);
}
}
// Disposes of the token.
public void Dispose() {
// Only allow a single call to Dispose.
int originalState = Interlocked.Exchange(ref _state, STATE_DISPOSING);
switch (originalState) {
case STATE_CREATED:
case STATE_CANCELED:
// If Cancel() hasn't yet been called or has already run to completion,
// the underlying CTS guarantees that the Dispose method won't block
// or throw, so we can just call it directly.
_cts.Dispose();
Interlocked.Exchange(ref _state, STATE_DISPOSED);
break;
case STATE_DISPOSED:
// If the object was already disposed, we need to reset the flag here
// since we accidentally blew it away with the original Exchange.
Interlocked.Exchange(ref _state, STATE_DISPOSED);
break;
// Otherwise, the object is already canceling or disposing, so the
// other thread will handle the call to Dispose().
}
}
private static CancellationTokenHelper GetStaticDisposedHelper() {
CancellationTokenHelper helper = new CancellationTokenHelper(false);
helper.Dispose();
return helper;
}
}
}

View File

@@ -0,0 +1,97 @@
//------------------------------------------------------------------------------
// <copyright file="CodePageUtils.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System.Collections;
//
// Utility class to help with determining if a given code page
// is ASCII compatible (preserves 0-127 Unicode characters as is)
//
internal static class CodePageUtils {
/* The following array of ASCII compatible code pages
is generated by running this code on a machine that
has _many_ codepages installed:
using System;
using System.Collections;
using System.Text;
public class qq {
public static void Main(string[] args) {
ArrayList list = new ArrayList();
byte[] bb = new byte[128]; for (int i = 0; i < 128; i++) bb[i] = (byte)i;
String asciiString = Encoding.ASCII.GetString(bb);
for (int i = 1; i < 100000; i++) {
try {
Encoding e = Encoding.GetEncoding(i);
byte[] xx = e.GetBytes(asciiString);
if (xx.Length == 128) {
bool good = true;
for (int j = 0; j < 128; j++) { if (bb[j] != xx[j]) { good = false; break; } }
if (good) list.Add(i);
}
}
catch {}
}
int n = list.Count;
Console.Write("private const int[] _asciiCompatCodePages = new int[" + n + "] {\r\n ");
for (int i = 0; i < n; i++) {
Console.Write("{0,5}", list[i]);
if (i < n-1) Console.Write(", ");
if (((i+1) % 10) == 0) Console.Write("\r\n ");
}
Console.Write("\r\n};\r\n");
}
}
*/
private static int[] _asciiCompatCodePages = new int[79] {
437, 708, 720, 737, 775, 850, 852, 855, 857, 858,
860, 861, 862, 863, 864, 865, 866, 869, 874, 932,
936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256,
1257, 1258, 1361, 10000, 10001, 10002, 10003, 10004, 10005, 10006,
10007, 10008, 10010, 10017, 10029, 10079, 10081, 10082, 20000, 20001,
20002, 20003, 20004, 20005, 20127, 20866, 20932, 20936, 20949, 21866,
28591, 28592, 28593, 28594, 28595, 28596, 28597, 28598, 28599, 28605,
38598, 50220, 50221, 50222, 50225, 50227, 51932, 51949, 65001
};
internal /*public*/ static bool IsAsciiCompatibleCodePage(int codepage) {
//alternatives to binary search considered
//Hashtable: static initialization increases startup up, perf relative
//Byte array would consume ~8K, but lookups constant
//with 80 entries, binary search limited to 7 indexes into array
int lo = 0;
int hi = 78;
while(lo <= hi) {
int i = (lo + hi) >> 1;
int c;
c = _asciiCompatCodePages[i] - codepage;
if (c == 0) return true; //i is the index of the item
if (c < 0) {
lo = i + 1;
}
else {
hi = i - 1;
}
}
return false;
//lo is the index of the item immediately after
//~lo returned in some implementations for false indicator with additional info
}
internal const int CodePageUT8 = 65001;
}
}

View File

@@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
// <copyright file="CountdownTask.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
using System.Threading;
using System.Threading.Tasks;
// This class is similar to CountdownEvent, but it uses Task under the covers
// instead of ManualResetEvent. When the internal counter hits zero, the Task
// is marked as complete.
//
// This type is thread-safe. Error checking is not performed in RET builds.
internal sealed class CountdownTask {
private int _pendingCount;
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
public CountdownTask(int initialCount) {
AddCount(initialCount);
}
public int CurrentCount {
get { return _pendingCount; }
}
public Task Task {
get { return _tcs.Task; }
}
private void AddCount(int delta) {
int newCount = Interlocked.Add(ref _pendingCount, delta);
Debug.Assert(newCount >= 0, "The counter should never hit a negative value.");
if (newCount == 0) {
bool success = _tcs.TrySetResult(null);
Debug.Assert(success, "TrySetResult shouldn't have been already called.");
}
}
public void MarkOperationCompleted() {
AddCount(-1);
}
public void MarkOperationPending() {
AddCount(+1);
}
}
}

View File

@@ -0,0 +1,67 @@
//------------------------------------------------------------------------------
// <copyright file="CultureUtil.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
using System.Globalization;
// This class contains helper methods for obtaining a CultureInfo instance from a list of candidates.
internal static class CultureUtil {
// Given a single culture name, attempts to turn it into a CultureInfo.
// If 'requireSpecific' is set, this method attempts to return an object where IsNeutral = false.
public static CultureInfo CreateReadOnlyCulture(string cultureName, bool requireSpecific) {
if (requireSpecific) {
return HttpServerUtility.CreateReadOnlySpecificCultureInfo(cultureName);
}
else {
return HttpServerUtility.CreateReadOnlyCultureInfo(cultureName);
}
}
// Given a list of culture names, loop through them until we find one we understand.
// We expect 'cultureNames' to be the raw Accept-Languages header value, as we'll strip q-values.
// Otherwise equivalent to the single-element overload.
public static CultureInfo CreateReadOnlyCulture(string[] cultureNames, bool requireSpecific) {
return ExtractCultureImpl(cultureNames, requireSpecific, AppSettings.MaxAcceptLanguageFallbackCount);
}
// for unit testing, uses 'maxCount' instead of the <appSettings> switch
internal static CultureInfo ExtractCultureImpl(string[] cultureNames, bool requireSpecific, int maxCount) {
int lastIndex = Math.Min(cultureNames.Length, maxCount) - 1;
for (int i = 0; i < cultureNames.Length; i++) {
string candidate = StripQValue(cultureNames[i]);
try {
return CreateReadOnlyCulture(candidate, requireSpecific);
}
catch (CultureNotFoundException) {
// If this is the last iteration before giving up, let the exception propagate upward.
// Otherwise just ---- and move on to the next candidate.
if (i == lastIndex) {
throw;
}
}
}
return null;
}
// Given an input "foo;q=xx", returns "foo".
private static string StripQValue(string input) {
if (input != null) {
int indexOfSemicolon = input.IndexOf(';');
if (indexOfSemicolon >= 0) {
return input.Substring(0, indexOfSemicolon);
}
}
return input;
}
}
}

View File

@@ -0,0 +1,52 @@
//------------------------------------------------------------------------------
// <copyright file="FileChangesMonitor.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
internal sealed class DateTimeUtil {
private DateTimeUtil() {}
const long FileTimeOffset = 504911232000000000;
static readonly DateTime MinValuePlusOneDay = DateTime.MinValue.AddDays(1);
static readonly DateTime MaxValueMinusOneDay = DateTime.MaxValue.AddDays(-1);
static internal DateTime FromFileTimeToUtc(long filetime) {
long universalTicks = filetime + FileTimeOffset;
// Dev10 733288: Caching: behavior change for CacheDependency when using UseMemoryCache=1
// ObjectCacheHost converts DateTime to a DateTimeOffset, and the conversion requires
// that DateTimeKind be set correctly
return new DateTime(universalTicks, DateTimeKind.Utc);
}
static internal DateTime ConvertToUniversalTime(DateTime localTime) {
if (localTime < MinValuePlusOneDay) {
return DateTime.MinValue;
}
if (localTime > MaxValueMinusOneDay) {
return DateTime.MaxValue;
}
return localTime.ToUniversalTime();
}
static internal DateTime ConvertToLocalTime(DateTime utcTime) {
if (utcTime < MinValuePlusOneDay) {
return DateTime.MinValue;
}
if (utcTime > MaxValueMinusOneDay) {
return DateTime.MaxValue;
}
return utcTime.ToLocalTime();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
//------------------------------------------------------------------------------
// <copyright file="DisposableAction.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
using System.Threading;
// Helper class for wrapping a continuation inside an IDisposable.
// This class is thread-safe.
internal sealed class DisposableAction : IDisposable {
public static readonly DisposableAction Empty = new DisposableAction(null);
private Action _disposeAction;
public DisposableAction(Action disposeAction) {
_disposeAction = disposeAction;
}
public void Dispose() {
// Interlocked allows the continuation to be executed only once
Action continuation = Interlocked.Exchange(ref _disposeAction, null);
if (continuation != null) {
continuation();
}
}
}
}

View File

@@ -0,0 +1,16 @@
//------------------------------------------------------------------------------
// <copyright file="DoNotResetAttribute.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Util {
using System;
// If this attribute is applied to a field, it will not be reset by a call to ReflectionUtil.Reset().
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
internal sealed class DoNotResetAttribute : Attribute {
}
}

View File

@@ -0,0 +1,65 @@
//------------------------------------------------------------------------------
// <copyright file="DoubleLink.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* DoubleLink
*
* Copyright (c) 1998-1999, Microsoft Corporation
*
*/
namespace System.Web.Util {
using System.Runtime.Serialization.Formatters;
internal class DoubleLink {
internal DoubleLink _next, _prev;
internal Object Item;
internal DoubleLink() {
_next = _prev = this;
}
internal DoubleLink(Object item) : this() {
this.Item = item;
}
internal DoubleLink Next {get {return _next;}}
internal void InsertAfter(DoubleLink after) {
this._prev = after;
this._next = after._next;
after._next = this;
this._next._prev = this;
}
internal void InsertBefore(DoubleLink before) {
this._prev = before._prev;
this._next = before;
before._prev = this;
this._prev._next = this;
}
internal void Remove() {
this._prev._next = this._next;
this._next._prev = this._prev;
_next = _prev = this;
}
#if DBG
internal virtual void DebugValidate() {
Debug.CheckValid(this._next != this || this._prev == this, "Invalid link");
}
internal virtual string DebugDescription(string indent) {
string desc;
desc = indent + "_next=" + _next + ", _prev=" + _prev + "\nItem=";
desc += Debug.GetDescription(Item, indent + " ");
return desc;
}
#endif
}
}

View File

@@ -0,0 +1,114 @@
//------------------------------------------------------------------------------
// <copyright file="DoubleLinkList.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* DoubleLinkList
*
* Copyright (c) 1998-1999, Microsoft Corporation
*
*/
namespace System.Web.Util {
using System.Text;
using System.Runtime.Serialization.Formatters;
internal class DoubleLinkList : DoubleLink {
internal DoubleLinkList() {
}
internal bool IsEmpty() {
return _next == this;
}
internal virtual void InsertHead(DoubleLink entry) {
entry.InsertAfter(this);
}
internal virtual void InsertTail(DoubleLink entry) {
entry.InsertBefore(this);
}
internal DoubleLinkListEnumerator GetEnumerator() {
return new DoubleLinkListEnumerator(this);
}
#if DBG
internal override void DebugValidate() {
DoubleLink l1, l2;
base.DebugValidate();
/*
* Detect loops by moving one pointer forward 2 for every 1
* of the other.
*/
l1 = l2 = this;
for (;;) {
/* move l2 forward */
l2 = l2._next;
if (l2 == this)
break;
Debug.CheckValid(l2 != l1, "Invalid loop in list, first move.");
l2.DebugValidate();
/* move l2 forward again */
l2 = l2._next;
if (l2 == this)
break;
Debug.CheckValid(l2 != l1, "Invalid loop in list, second move.");
l2.DebugValidate();
/* move l1 forward */
l1 = l1._next;
}
}
internal override string DebugDescription(String indent) {
string desc;
DoubleLinkListEnumerator lenum;
int c;
StringBuilder sb;
string i2 = indent + " ";
if (IsEmpty()) {
desc = indent + "DoubleLinkList is empty\n";
}
else {
c = Length;
sb = new StringBuilder(indent + "DoubleLinkList has " + c + " entries.\n");
lenum = GetEnumerator();
while (lenum.MoveNext()) {
sb.Append(Debug.GetDescription(lenum.GetDoubleLink(), i2));
}
desc = sb.ToString();
}
return desc;
}
#endif
internal int Length {
get {
DoubleLinkListEnumerator lenum;
int c;
Debug.Validate(this);
c = 0;
lenum = GetEnumerator();
while (lenum.MoveNext()) {
c++;
}
return c;
}
}
}
}

View File

@@ -0,0 +1,53 @@
//------------------------------------------------------------------------------
// <copyright file="DoubleLinkListEnumerator.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* DoubleLinkList
*
* Copyright (c) 1998-1999, Microsoft Corporation
*
*/
namespace System.Web.Util {
using System.Runtime.Serialization.Formatters;
using System.Collections;
internal class DoubleLinkListEnumerator : IEnumerator {
private DoubleLinkList _list;
private DoubleLink _current;
internal DoubleLinkListEnumerator(DoubleLinkList list) {
_list = list;
_current = list;
}
public void Reset() {
_current = _list;
}
public bool MoveNext() {
if (_current.Next == _list) {
_current = null;
return false;
}
_current = _current.Next;
return true;
}
public Object Current {
get {
if (_current == null || _current == _list)
throw new InvalidOperationException();
return _current.Item;
}
}
internal DoubleLink GetDoubleLink() {
return _current;
}
}
}

Some files were not shown because too many files have changed in this diff Show More